[Qemu-devel] [Bug 1299566] [NEW] virtio serial doesn't work with virtio nic
Public bug reported: If virtio NIC is not used virtserialport works and delivers data written to /dev/vport0p1 to localhost:: qemu-system-x86_64 -enable-kvm -kernel mykernel -initrd myramdisk -device virtio-serial -chardev socket,host=localhost,port=,id=agent -device virtserialport,chardev=agent,name=hera.agent -net user -net nic If using virtio nic, write to /dev/vport0p1 succeeds, but no data is delivered to localhost:: qemu-system-x86_64 -enable-kvm -kernel mykernel -initrd myramdisk -device virtio-serial -chardev socket,host=localhost,port=,id=agent -device virtserialport,chardev=agent,name=hera.agent -net user -net nic,model=virtio This bug exists in 2.0 release, Debian's QEMU 1.7 package and b3706faf from git. ** Affects: qemu Importance: Undecided Status: New -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1299566 Title: virtio serial doesn't work with virtio nic Status in QEMU: New Bug description: If virtio NIC is not used virtserialport works and delivers data written to /dev/vport0p1 to localhost:: qemu-system-x86_64 -enable-kvm -kernel mykernel -initrd myramdisk -device virtio-serial -chardev socket,host=localhost,port=,id=agent -device virtserialport,chardev=agent,name=hera.agent -net user -net nic If using virtio nic, write to /dev/vport0p1 succeeds, but no data is delivered to localhost:: qemu-system-x86_64 -enable-kvm -kernel mykernel -initrd myramdisk -device virtio-serial -chardev socket,host=localhost,port=,id=agent -device virtserialport,chardev=agent,name=hera.agent -net user -net nic,model=virtio This bug exists in 2.0 release, Debian's QEMU 1.7 package and b3706faf from git. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1299566/+subscriptions
[Qemu-devel] [PATCH v2 09/17] monitor: Add netdev_del id argument completion.
Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 1 + hmp.h | 1 + monitor.c | 26 ++ 3 files changed, 28 insertions(+) diff --git a/hmp-commands.hx b/hmp-commands.hx index b009561..d252ffc 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1244,6 +1244,7 @@ ETEXI .params = id, .help = remove host network device, .mhandler.cmd = hmp_netdev_del, +.command_completion = netdev_del_completion, }, STEXI diff --git a/hmp.h b/hmp.h index 9dab1a3..c98722b 100644 --- a/hmp.h +++ b/hmp.h @@ -102,5 +102,6 @@ void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str); void cpu_completion(ReadLineState *rs, int nb_args, const char *str); void set_link_completion(ReadLineState *rs, int nb_args, const char *str); void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str); +void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str); #endif diff --git a/monitor.c b/monitor.c index 5293370..d1b0d6c 100644 --- a/monitor.c +++ b/monitor.c @@ -4505,6 +4505,32 @@ void set_link_completion(ReadLineState *rs, int nb_args, const char *str) } } +void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str) +{ +int len, count, i; +NetClientState *ncs[255]; + +if (nb_args != 2) { +return; +} + +len = strlen(str); +readline_set_completion_index(rs, len); +count = qemu_find_net_clients_except(NULL, ncs, NET_CLIENT_OPTIONS_KIND_NIC, + 255); +for (i = 0; i count; i++) { +QemuOpts *opts; +const char *name = ncs[i]-name; +if (strncmp(str, name, len)) { +continue; +} +opts = qemu_opts_find(qemu_find_opts_err(netdev, NULL), name); +if (opts) { +readline_add_completion(rs, name); +} +} +} + static void monitor_find_completion_by_table(Monitor *mon, const mon_cmd_t *cmd_table, char **args, -- 1.8.3.2
[Qemu-devel] [PATCH v2 00/17] monitor: Completion support for various commands
This patch series adds a new callback to mon_cmd_t which will make adding completion support for more commands cleaner. It then adds full or partial arguments completion for multiple hmp commands. Changes since v1: * Splitting patch 1/7 to 1/17, 2/17 and 3/17. * Changed command_completion's first argument from Monitor to ReadLineState. * Added new commands completions (10/17 to 17/17) Hani Benhabiles (17): monitor: Fix drive_del id argument type completion. monitor: Add command_completion callback to mon_cmd_t. monitor: Add device_add and device_del completion. monitor: Add chardev-remove id argument completion. monitor: Add chardev-add backend argument completion. monitor: Add cpu index argument completion. monitor: Add set_link arguments completion. monitor: Add netdev_add type argument completion. monitor: Add netdev_del id argument completion. monitor: Add ringbuf_write and ringbuf_read argument completion. monitor: Add watchdog_action argument completion. monitor: Add migrate_set_capability completion. monitor: Add host_net_add device argument completion. readline: Make completion strings always unique. monitor: Add host_net_remove arguments completion. monitor: Add mouse_set index argument completion. monitor: Add delvm and loadvm argument completion. hmp-commands.hx | 25 +++- hmp.h | 23 +++ include/sysemu/char.h | 3 +- monitor.c | 397 +++--- net/net.c | 2 +- qemu-char.c | 2 +- util/readline.c | 6 + 7 files changed, 432 insertions(+), 26 deletions(-) -- 1.8.3.2
[Qemu-devel] [PATCH v2 13/17] monitor: Add host_net_add device argument completion.
Also fix the parameters documentation. Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 3 ++- hmp.h | 1 + monitor.c | 14 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 8c674ba..9da5866 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1201,9 +1201,10 @@ ETEXI { .name = host_net_add, .args_type = device:s,opts:s?, -.params = tap|user|socket|vde|netmap|dump [options], +.params = tap|user|socket|vde|bridge|dump [options], .help = add host VLAN client, .mhandler.cmd = net_host_device_add, +.command_completion = host_net_add_completion, }, STEXI diff --git a/hmp.h b/hmp.h index 3570530..c82fd87 100644 --- a/hmp.h +++ b/hmp.h @@ -109,5 +109,6 @@ void watchdog_action_completion(ReadLineState *rs, int nb_args, const char *str); void migrate_set_capability_completion(ReadLineState *rs, int nb_args, const char *str); +void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str); #endif diff --git a/monitor.c b/monitor.c index 2974a66..4c20bc5 100644 --- a/monitor.c +++ b/monitor.c @@ -4605,6 +4605,20 @@ void migrate_set_capability_completion(ReadLineState *rs, int nb_args, } } +void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str) +{ +if (nb_args != 2) { +return; +} +readline_set_completion_index(rs, strlen(str)); +add_completion_option(rs, str, tap); +add_completion_option(rs, str, user); +add_completion_option(rs, str, socket); +add_completion_option(rs, str, vde); +add_completion_option(rs, str, dump); +add_completion_option(rs, str, bridge); +} + static void monitor_find_completion_by_table(Monitor *mon, const mon_cmd_t *cmd_table, char **args, -- 1.8.3.2
[Qemu-devel] [PATCH v2 07/17] monitor: Add set_link arguments completion.
Make it possible to query all net clients without specifying an ID when calling qemu_find_net_clients_except(). This also adds the add_completion_option() function which is to be used for other commands completions as well. Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 1 + hmp.h | 1 + monitor.c | 34 ++ net/net.c | 2 +- 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 813c0fb..fbd303a 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1332,6 +1332,7 @@ ETEXI .params = name on|off, .help = change the link status of a network adapter, .mhandler.cmd = hmp_set_link, +.command_completion = set_link_completion, }, STEXI diff --git a/hmp.h b/hmp.h index 8701b16..33a883d 100644 --- a/hmp.h +++ b/hmp.h @@ -100,5 +100,6 @@ void device_del_completion(ReadLineState *rs, int nb_args, const char *str); void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str); void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str); void cpu_completion(ReadLineState *rs, int nb_args, const char *str); +void set_link_completion(ReadLineState *rs, int nb_args, const char *str); #endif diff --git a/monitor.c b/monitor.c index 29d4f37..009f269 100644 --- a/monitor.c +++ b/monitor.c @@ -4278,6 +4278,17 @@ static const char *next_arg_type(const char *typestr) return (p != NULL ? ++p : typestr); } +static void add_completion_option(ReadLineState *rs, const char *str, + const char *option) +{ +if (!str || !option) { +return; +} +if (!strncmp(option, str, strlen(str))) { +readline_add_completion(rs, option); +} +} + void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str) { size_t len; @@ -4453,6 +4464,29 @@ void cpu_completion(ReadLineState *rs, int nb_args, const char *str) qapi_free_CpuInfoList(start); } +void set_link_completion(ReadLineState *rs, int nb_args, const char *str) +{ +size_t len; + +len = strlen(str); +readline_set_completion_index(rs, len); +if (nb_args == 2) { +NetClientState *ncs[255]; +int count, i; +count = qemu_find_net_clients_except(NULL, ncs, + NET_CLIENT_OPTIONS_KIND_NONE, 255); +for (i = 0; i count; i++) { +const char *name = ncs[i]-name; +if (!strncmp(str, name, len)) { +readline_add_completion(rs, name); +} +} +} else if (nb_args == 3) { +add_completion_option(rs, str, on); +add_completion_option(rs, str, off); +} +} + static void monitor_find_completion_by_table(Monitor *mon, const mon_cmd_t *cmd_table, char **args, diff --git a/net/net.c b/net/net.c index e3ef1e4..86dd051 100644 --- a/net/net.c +++ b/net/net.c @@ -633,7 +633,7 @@ int qemu_find_net_clients_except(const char *id, NetClientState **ncs, if (nc-info-type == type) { continue; } -if (!strcmp(nc-name, id)) { +if (!id || !strcmp(nc-name, id)) { if (ret max) { ncs[ret] = nc; } -- 1.8.3.2
[Qemu-devel] [PATCH v2 08/17] monitor: Add netdev_add type argument completion.
Also update the command's documentation. Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 3 ++- hmp.h | 1 + monitor.c | 18 ++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index fbd303a..b009561 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1226,9 +1226,10 @@ ETEXI { .name = netdev_add, .args_type = netdev:O, -.params = [user|tap|socket|hubport|netmap],id=str[,prop=value][,...], +.params = [user|tap|socket|vde|bridge|hubport|netmap],id=str[,prop=value][,...], .help = add host network device, .mhandler.cmd = hmp_netdev_add, +.command_completion = netdev_add_completion, }, STEXI diff --git a/hmp.h b/hmp.h index 33a883d..9dab1a3 100644 --- a/hmp.h +++ b/hmp.h @@ -101,5 +101,6 @@ void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str); void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str); void cpu_completion(ReadLineState *rs, int nb_args, const char *str); void set_link_completion(ReadLineState *rs, int nb_args, const char *str); +void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str); #endif diff --git a/monitor.c b/monitor.c index 009f269..5293370 100644 --- a/monitor.c +++ b/monitor.c @@ -4312,6 +4312,24 @@ void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str) qapi_free_ChardevBackendInfoList(start); } +void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str) +{ +size_t len; + +if (nb_args != 2) { +return; +} +len = strlen(str); +readline_set_completion_index(rs, len); +add_completion_option(rs, str, user); +add_completion_option(rs, str, tap); +add_completion_option(rs, str, socket); +add_completion_option(rs, str, vde); +add_completion_option(rs, str, bridge); +add_completion_option(rs, str, hubport); +add_completion_option(rs, str, netmap); +} + void device_add_completion(ReadLineState *rs, int nb_args, const char *str) { GSList *list, *elt; -- 1.8.3.2
[Qemu-devel] [PATCH v2 04/17] monitor: Add chardev-remove id argument completion.
Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 1 + hmp.h | 1 + monitor.c | 23 +++ 3 files changed, 25 insertions(+) diff --git a/hmp-commands.hx b/hmp-commands.hx index 4c4d261..4f0f053 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1630,6 +1630,7 @@ ETEXI .params = id, .help = remove chardev, .mhandler.cmd = hmp_chardev_remove, +.command_completion = chardev_remove_completion, }, STEXI diff --git a/hmp.h b/hmp.h index 20ef454..42b4d6b 100644 --- a/hmp.h +++ b/hmp.h @@ -97,5 +97,6 @@ void object_add_completion(ReadLineState *rs, int nb_args, const char *str); void object_del_completion(ReadLineState *rs, int nb_args, const char *str); void device_add_completion(ReadLineState *rs, int nb_args, const char *str); void device_del_completion(ReadLineState *rs, int nb_args, const char *str); +void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str); #endif diff --git a/monitor.c b/monitor.c index 710ba25..040da9b 100644 --- a/monitor.c +++ b/monitor.c @@ -4346,6 +4346,29 @@ static void device_del_bus_completion(ReadLineState *rs, BusState *bus, } } +void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str) +{ +size_t len; +ChardevInfoList *list, *start; + +if (nb_args != 2) { +return; +} +len = strlen(str); +readline_set_completion_index(rs, len); + +start = list = qmp_query_chardev(NULL); +while (list) { +ChardevInfo *chr = list-value; + +if (!strncmp(chr-label, str, len)) { +readline_add_completion(rs, chr-label); +} +list = list-next; +} +qapi_free_ChardevInfoList(start); +} + void device_del_completion(ReadLineState *rs, int nb_args, const char *str) { size_t len; -- 1.8.3.2
[Qemu-devel] [PATCH v2 11/17] monitor: Add watchdog_action argument completion.
Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 1 + hmp.h | 2 ++ monitor.c | 14 ++ 3 files changed, 17 insertions(+) diff --git a/hmp-commands.hx b/hmp-commands.hx index 300be4e..669a845 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1351,6 +1351,7 @@ ETEXI .params = [reset|shutdown|poweroff|pause|debug|none], .help = change watchdog action, .mhandler.cmd = do_watchdog_action, +.command_completion = watchdog_action_completion, }, STEXI diff --git a/hmp.h b/hmp.h index d7d0770..eca50b4 100644 --- a/hmp.h +++ b/hmp.h @@ -105,5 +105,7 @@ void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str); void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str); void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str); void ringbuf_read_completion(ReadLineState *rs, int nb_args, const char *str); +void watchdog_action_completion(ReadLineState *rs, int nb_args, +const char *str); #endif diff --git a/monitor.c b/monitor.c index 839f8f1..cb1fb7c 100644 --- a/monitor.c +++ b/monitor.c @@ -4570,6 +4570,20 @@ void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str) } } +void watchdog_action_completion(ReadLineState *rs, int nb_args, const char *str) +{ +if (nb_args != 2) { +return; +} +readline_set_completion_index(rs, strlen(str)); +add_completion_option(rs, str, reset); +add_completion_option(rs, str, shutdown); +add_completion_option(rs, str, poweroff); +add_completion_option(rs, str, pause); +add_completion_option(rs, str, debug); +add_completion_option(rs, str, none); +} + static void monitor_find_completion_by_table(Monitor *mon, const mon_cmd_t *cmd_table, char **args, -- 1.8.3.2
[Qemu-devel] [PATCH v2 15/17] monitor: Add host_net_remove arguments completion.
Relies on readline unique completion strings patch to make the added vlan/hub completion values unique, instead of using something like a hash table. Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 1 + hmp.h | 2 ++ monitor.c | 38 ++ 3 files changed, 41 insertions(+) diff --git a/hmp-commands.hx b/hmp-commands.hx index 9da5866..b41a6d6 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1219,6 +1219,7 @@ ETEXI .params = vlan_id name, .help = remove host VLAN client, .mhandler.cmd = net_host_device_remove, +.command_completion = host_net_remove_completion, }, STEXI diff --git a/hmp.h b/hmp.h index c82fd87..12f0364 100644 --- a/hmp.h +++ b/hmp.h @@ -110,5 +110,7 @@ void watchdog_action_completion(ReadLineState *rs, int nb_args, void migrate_set_capability_completion(ReadLineState *rs, int nb_args, const char *str); void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str); +void host_net_remove_completion(ReadLineState *rs, int nb_args, +const char *str); #endif diff --git a/monitor.c b/monitor.c index 4c20bc5..9781ee2 100644 --- a/monitor.c +++ b/monitor.c @@ -4619,6 +4619,44 @@ void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str) add_completion_option(rs, str, bridge); } +void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str) +{ +NetClientState *ncs[255]; +int count, i, len; + +len = strlen(str); +readline_set_completion_index(rs, len); +if (nb_args == 2) { +count = qemu_find_net_clients_except(NULL, ncs, + NET_CLIENT_OPTIONS_KIND_NONE, 255); +for (i = 0; i count; i++) { +int id; +char name[16]; + +if (net_hub_id_for_client(ncs[i], id)) { +continue; +} +snprintf(name, sizeof(name), %d, id); +if (!strncmp(str, name, len)) { +readline_add_completion(rs, name); +} +} +return; +} else if (nb_args == 3) { +count = qemu_find_net_clients_except(NULL, ncs, + NET_CLIENT_OPTIONS_KIND_NIC, 255); +for (i = 0; i count; i++) { +const char *name; + +name = ncs[i]-name; +if (!strncmp(str, name, len)) { +readline_add_completion(rs, name); +} +} +return; +} +} + static void monitor_find_completion_by_table(Monitor *mon, const mon_cmd_t *cmd_table, char **args, -- 1.8.3.2
[Qemu-devel] [PATCH v2 05/17] monitor: Add chardev-add backend argument completion.
Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 1 + hmp.h | 1 + monitor.c | 23 +++ 3 files changed, 25 insertions(+) diff --git a/hmp-commands.hx b/hmp-commands.hx index 4f0f053..a411d4f 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1614,6 +1614,7 @@ ETEXI .params = args, .help = add chardev, .mhandler.cmd = hmp_chardev_add, +.command_completion = chardev_add_completion, }, STEXI diff --git a/hmp.h b/hmp.h index 42b4d6b..6de5d1a 100644 --- a/hmp.h +++ b/hmp.h @@ -98,5 +98,6 @@ void object_del_completion(ReadLineState *rs, int nb_args, const char *str); void device_add_completion(ReadLineState *rs, int nb_args, const char *str); void device_del_completion(ReadLineState *rs, int nb_args, const char *str); void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str); +void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str); #endif diff --git a/monitor.c b/monitor.c index 040da9b..27caa74 100644 --- a/monitor.c +++ b/monitor.c @@ -4278,6 +4278,29 @@ static const char *next_arg_type(const char *typestr) return (p != NULL ? ++p : typestr); } +void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str) +{ +size_t len; +ChardevBackendInfoList *list, *start; + +if (nb_args != 2) { +return; +} +len = strlen(str); +readline_set_completion_index(rs, len); + +start = list = qmp_query_chardev_backends(NULL); +while (list) { +const char *chr_name = list-value-name; + +if (!strncmp(chr_name, str, len)) { +readline_add_completion(rs, chr_name); +} +list = list-next; +} +qapi_free_ChardevBackendInfoList(start); +} + void device_add_completion(ReadLineState *rs, int nb_args, const char *str) { GSList *list, *elt; -- 1.8.3.2
[Qemu-devel] [PATCH v2 14/17] readline: Make completion strings always unique.
There is no need to clutter the user's choices with repeating the same value multiple times. Signed-off-by: Hani Benhabiles h...@linux.com --- util/readline.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/util/readline.c b/util/readline.c index 8441be4..6aeae6a 100644 --- a/util/readline.c +++ b/util/readline.c @@ -263,6 +263,12 @@ static void readline_hist_add(ReadLineState *rs, const char *cmdline) void readline_add_completion(ReadLineState *rs, const char *str) { if (rs-nb_completions READLINE_MAX_COMPLETIONS) { +int i; +for (i = 0; i rs-nb_completions; i++) { +if (!strcmp(rs-completions[i], str)) { +return; +} +} rs-completions[rs-nb_completions++] = g_strdup(str); } } -- 1.8.3.2
[Qemu-devel] [PATCH v2 06/17] monitor: Add cpu index argument completion.
Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 1 + hmp.h | 1 + monitor.c | 24 3 files changed, 26 insertions(+) diff --git a/hmp-commands.hx b/hmp-commands.hx index a411d4f..813c0fb 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -690,6 +690,7 @@ ETEXI .params = index, .help = set the default CPU, .mhandler.cmd = hmp_cpu, +.command_completion = cpu_completion, }, STEXI diff --git a/hmp.h b/hmp.h index 6de5d1a..8701b16 100644 --- a/hmp.h +++ b/hmp.h @@ -99,5 +99,6 @@ void device_add_completion(ReadLineState *rs, int nb_args, const char *str); void device_del_completion(ReadLineState *rs, int nb_args, const char *str); void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str); void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str); +void cpu_completion(ReadLineState *rs, int nb_args, const char *str); #endif diff --git a/monitor.c b/monitor.c index 27caa74..29d4f37 100644 --- a/monitor.c +++ b/monitor.c @@ -4429,6 +4429,30 @@ void object_del_completion(ReadLineState *rs, int nb_args, const char *str) qapi_free_ObjectPropertyInfoList(start); } +void cpu_completion(ReadLineState *rs, int nb_args, const char *str) +{ +CpuInfoList *cpu_list, *start; +size_t len; + +if (nb_args != 2) { +return; +} +len = strlen(str); +readline_set_completion_index(rs, len); + +start = cpu_list = qmp_query_cpus(NULL); +while (cpu_list) { +char name[16]; +snprintf(name, sizeof(name), % PRId64, cpu_list-value-CPU); + +if (!strncmp(str, name, len)) { +readline_add_completion(rs, name); +} +cpu_list = cpu_list-next; +} +qapi_free_CpuInfoList(start); +} + static void monitor_find_completion_by_table(Monitor *mon, const mon_cmd_t *cmd_table, char **args, -- 1.8.3.2
[Qemu-devel] [chet.ens...@oasis-open.org: [members] 15-day Public Review for Virtual I/O Device (VIRTIO) V1.0 - ends 14 April]
- Forwarded message from Chet Ensign chet.ens...@oasis-open.org - Date: Fri, 28 Mar 2014 17:54:16 -0400 From: Chet Ensign chet.ens...@oasis-open.org To: tc-annou...@lists.oasis-open.org, memb...@lists.oasis-open.org, vir...@lists.oasis-open.org, virtio-comm...@lists.oasis-open.org Subject: [members] 15-day Public Review for Virtual I/O Device (VIRTIO) V1.0 - ends 14 April Message-ID: caawgnnpirq2pqamn7hpwx0izmqrhx+udjtssv8cvxznkf4h...@mail.gmail.com The OASIS Virtual I/O Device (VIRTIO) TC members [1] have produced an updated Committee Specification Draft (CSD) and submitted this specification for 15-day public review: Virtual I/O Device (VIRTIO) Version 1.0 Committee Specification Draft 02 / Public Review Draft 02 11 March 2014 With the release we are testing a convenience option for submitting comments to the Technical Committee. Please see the details under ‘Public Review Period’ below. Specification Overview: This document describes the specifications of the virtio family of devices. These devices are found in virtual environments, yet by design they are not all that different from physical devices, and this document treats them as such. This allows the guest to use standard drivers and discovery mechanisms. The purpose of virtio and this specification is that virtual environments and guests should have a straightforward, efficient, standard and extensible mechanism for virtual devices, rather than boutique per-environment or per-OS mechanisms. This is the second public review draft, incorporating significant feedback on clarity from the first draft. TC Description: The TC has spent the past two months processing all the feedback for incorporation into the document. We believe the result is a clearer, crisper draft and welcome further feedback. There are only a small number of changes to the intent of the spec, and these are highlighted at the top of the changelog. Public Review Period: The public review starts 31 March 2014 at 00:00 GMT and ends 14 April 2014 at 23:59 GMT. The specification was previously submitted for public review [2]. Due to the extensive number of changes, the complete Committee Specification Draft is open for review. This is an open invitation to comment. OASIS solicits feedback from potential users, developers and others, whether OASIS members or not, for the sake of improving the interoperability and quality of its technical work. With this public review, we are testing a new convenience feature for sending comments to the Technical Committee. The file http://docs.oasis-open.org/virtio/virtio/v1.0/csprd02/ virtio-v1.0-csprd02-COMMENT-TAGS.html contains the HTML version of the draft with a “[comment?]” link next to each section heading. Clicking on this link will launch your email application and begin a message to virtio-comm...@lists.oasis-open.org with the specific section number and title in the subject line. (For example, “Public review comment for virtio-v1.0-csprd02: 1.3 Terminology.”) Simply enter your comment and click send. You must be subscribed to the virtio-comm...@lists.oasis-open.org mailing list in order to send your comments. Instructions on how to subscribe can be found at https://www.oasis-open.org/committees/comments/index.php?wg_abbrev=virtio. Note that the Table of Contents doesn’t work in this version and other internal document links may not work in this file. That is one of the items we need fix before making this capability more broadly available. Please feel free to let us know if you find this feature helpful. We plan to refine it and make it a part of our normal public review process. URIs: The prose specification document and related files are available here: Editable source (Authoritative): http://docs.oasis-open.org/virtio/virtio/v1.0/csprd02/tex/ HTML: http://docs.oasis-open.org/virtio/virtio/v1.0/csprd02/virtio-v1.0-csprd02.html PDF: http://docs.oasis-open.org/virtio/virtio/v1.0/csprd02/virtio-v1.0-csprd02.pdf ZIP distribution files (complete): For your convenience, OASIS provides a complete package of the prose specification and related files in a ZIP distribution file. You can download the ZIP file here: http://docs.oasis-open.org/virtio/virtio/v1.0/csprd02/virtio-v1.0-csprd02.zip Additional information about this specification and the VIRTIO TC may be found on the TC's public home page located at: http://www.oasis-open.org/committees/virtio/ Comments may be submitted to the TC by any person through the use of the OASIS TC Comment Facility which can be accessed via the button labeled Send A Comment at the top of the TC public home page, or directly at: http://www.oasis-open.org/committees/comments/form.php?wg_abbrev=virtio Feedback submitted by TC non-members for this work and for other work of this TC is publicly archived and can be viewed at: http://lists.oasis-open.org/archives/virtio-comment/ All comments submitted to OASIS are subject to the OASIS Feedback License, which ensures that the
[Qemu-devel] [PATCH v2 17/17] monitor: Add delvm and loadvm argument completion.
Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 2 ++ hmp.h | 2 ++ monitor.c | 48 3 files changed, 52 insertions(+) diff --git a/hmp-commands.hx b/hmp-commands.hx index 04aa059..b59d0e0 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -335,6 +335,7 @@ ETEXI .params = tag|id, .help = restore a VM snapshot from its tag or id, .mhandler.cmd = do_loadvm, +.command_completion = loadvm_completion, }, STEXI @@ -350,6 +351,7 @@ ETEXI .params = tag|id, .help = delete a VM snapshot from its tag or id, .mhandler.cmd = do_delvm, +.command_completion = delvm_completion, }, STEXI diff --git a/hmp.h b/hmp.h index 6e76473..40d1513 100644 --- a/hmp.h +++ b/hmp.h @@ -113,5 +113,7 @@ void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str); void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str); void mouse_set_completion(ReadLineState *rs, int nb_args, const char *str); +void delvm_completion(ReadLineState *rs, int nb_args, const char *str); +void loadvm_completion(ReadLineState *rs, int nb_args, const char *str); #endif diff --git a/monitor.c b/monitor.c index 385fb70..ed57455 100644 --- a/monitor.c +++ b/monitor.c @@ -69,6 +69,7 @@ #include qmp-commands.h #include hmp.h #include qemu/thread.h +#include block/qapi.h /* for pic/irq_info */ #if defined(TARGET_SPARC) @@ -4679,6 +4680,53 @@ void mouse_set_completion(ReadLineState *rs, int nb_args, const char *str) qapi_free_MouseInfoList(mice_list); } +static void vm_completion(ReadLineState *rs, const char *str) +{ +size_t len; +BlockDriverState *bs = NULL; + +len = strlen(str); +readline_set_completion_index(rs, len); +while ((bs = bdrv_next(bs))) { +SnapshotInfoList *snapshots, *snapshot; + +if (!bdrv_can_snapshot(bs)) { +continue; +} +if (bdrv_query_snapshot_info_list(bs, snapshots, NULL)) { +continue; +} +snapshot = snapshots; +while (snapshot) { +char *completion = snapshot-value-name; +if (!strncmp(str, completion, len)) { +readline_add_completion(rs, completion); +} +completion = snapshot-value-id; +if (!strncmp(str, completion, len)) { +readline_add_completion(rs, completion); +} +snapshot = snapshot-next; +} +qapi_free_SnapshotInfoList(snapshots); +} + +} + +void delvm_completion(ReadLineState *rs, int nb_args, const char *str) +{ +if (nb_args == 2) { +vm_completion(rs, str); +} +} + +void loadvm_completion(ReadLineState *rs, int nb_args, const char *str) +{ +if (nb_args == 2) { +vm_completion(rs, str); +} +} + static void monitor_find_completion_by_table(Monitor *mon, const mon_cmd_t *cmd_table, char **args, -- 1.8.3.2
[Qemu-devel] [PATCH v2 10/17] monitor: Add ringbuf_write and ringbuf_read argument completion.
Export chr_is_ringbuf() function. Also remove left-over function prototypes while at it. Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 2 ++ hmp.h | 2 ++ include/sysemu/char.h | 3 +-- monitor.c | 39 +++ qemu-char.c | 2 +- 5 files changed, 45 insertions(+), 3 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index d252ffc..300be4e 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -852,6 +852,7 @@ ETEXI .params = device data, .help = Write to a ring buffer character device, .mhandler.cmd = hmp_ringbuf_write, +.command_completion = ringbuf_write_completion, }, STEXI @@ -868,6 +869,7 @@ ETEXI .params = device size, .help = Read from a ring buffer character device, .mhandler.cmd = hmp_ringbuf_read, +.command_completion = ringbuf_write_completion, }, STEXI diff --git a/hmp.h b/hmp.h index c98722b..d7d0770 100644 --- a/hmp.h +++ b/hmp.h @@ -103,5 +103,7 @@ void cpu_completion(ReadLineState *rs, int nb_args, const char *str); void set_link_completion(ReadLineState *rs, int nb_args, const char *str); void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str); void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str); +void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str); +void ringbuf_read_completion(ReadLineState *rs, int nb_args, const char *str); #endif diff --git a/include/sysemu/char.h b/include/sysemu/char.h index b81a6ff..7f5eeb3 100644 --- a/include/sysemu/char.h +++ b/include/sysemu/char.h @@ -286,9 +286,8 @@ void qemu_chr_add_handlers(CharDriverState *s, void qemu_chr_be_generic_open(CharDriverState *s); void qemu_chr_accept_input(CharDriverState *s); int qemu_chr_add_client(CharDriverState *s, int fd); -void qemu_chr_info_print(Monitor *mon, const QObject *ret_data); -void qemu_chr_info(Monitor *mon, QObject **ret_data); CharDriverState *qemu_chr_find(const char *name); +bool chr_is_ringbuf(const CharDriverState *chr); QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename); diff --git a/monitor.c b/monitor.c index d1b0d6c..839f8f1 100644 --- a/monitor.c +++ b/monitor.c @@ -4421,6 +4421,45 @@ void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str) qapi_free_ChardevInfoList(start); } +static void ringbuf_completion(ReadLineState *rs, const char *str) +{ +size_t len; +ChardevInfoList *list, *start; + +len = strlen(str); +readline_set_completion_index(rs, len); + +start = list = qmp_query_chardev(NULL); +while (list) { +ChardevInfo *chr_info = list-value; + +if (!strncmp(chr_info-label, str, len)) { +CharDriverState *chr = qemu_chr_find(chr_info-label); +if (chr chr_is_ringbuf(chr)) { +readline_add_completion(rs, chr_info-label); +} +} +list = list-next; +} +qapi_free_ChardevInfoList(start); +} + +void ringbuf_read_completion(ReadLineState *rs, int nb_args, const char *str) +{ +if (nb_args != 2) { +return; +} +ringbuf_completion(rs, str); +} + +void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str) +{ +if (nb_args != 2) { +return; +} +ringbuf_completion(rs, str); +} + void device_del_completion(ReadLineState *rs, int nb_args, const char *str) { size_t len; diff --git a/qemu-char.c b/qemu-char.c index 54ed244..34c8f08 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2849,7 +2849,7 @@ fail: return NULL; } -static bool chr_is_ringbuf(const CharDriverState *chr) +bool chr_is_ringbuf(const CharDriverState *chr) { return chr-chr_write == ringbuf_chr_write; } -- 1.8.3.2
[Qemu-devel] [PATCH v2 16/17] monitor: Add mouse_set index argument completion.
Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 1 + hmp.h | 1 + monitor.c | 22 ++ 3 files changed, 24 insertions(+) diff --git a/hmp-commands.hx b/hmp-commands.hx index b41a6d6..04aa059 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -734,6 +734,7 @@ ETEXI .params = index, .help = set which mouse device receives events, .mhandler.cmd = do_mouse_set, +.command_completion = mouse_set_completion, }, STEXI diff --git a/hmp.h b/hmp.h index 12f0364..6e76473 100644 --- a/hmp.h +++ b/hmp.h @@ -112,5 +112,6 @@ void migrate_set_capability_completion(ReadLineState *rs, int nb_args, void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str); void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str); +void mouse_set_completion(ReadLineState *rs, int nb_args, const char *str); #endif diff --git a/monitor.c b/monitor.c index 9781ee2..385fb70 100644 --- a/monitor.c +++ b/monitor.c @@ -4657,6 +4657,28 @@ void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str) } } +void mouse_set_completion(ReadLineState *rs, int nb_args, const char *str) +{ +size_t len; +MouseInfoList *mice_list, *mouse; +if (nb_args != 2) { +return; +} +len = strlen(str); +readline_set_completion_index(rs, len); +mice_list = mouse = qmp_query_mice(NULL); +while (mouse) { +char name[16]; +snprintf(name, sizeof(name), % PRId64, mouse-value-index); + +if (!strncmp(str, name, len)) { +readline_add_completion(rs, name); +} +mouse = mouse-next; +} +qapi_free_MouseInfoList(mice_list); +} + static void monitor_find_completion_by_table(Monitor *mon, const mon_cmd_t *cmd_table, char **args, -- 1.8.3.2
[Qemu-devel] [PATCH v2 01/17] monitor: Fix drive_del id argument type completion.
Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index f3fc514..6bf4797 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -176,7 +176,7 @@ ETEXI { .name = drive_del, -.args_type = id:s, +.args_type = id:B, .params = device, .help = remove host block device, .user_print = monitor_user_noop, -- 1.8.3.2
[Qemu-devel] [PATCH v2 12/17] monitor: Add migrate_set_capability completion.
Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 1 + hmp.h | 2 ++ monitor.c | 21 + 3 files changed, 24 insertions(+) diff --git a/hmp-commands.hx b/hmp-commands.hx index 669a845..8c674ba 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -975,6 +975,7 @@ ETEXI .params = capability state, .help = Enable/Disable the usage of a capability for migration, .mhandler.cmd = hmp_migrate_set_capability, +.command_completion = migrate_set_capability_completion, }, STEXI diff --git a/hmp.h b/hmp.h index eca50b4..3570530 100644 --- a/hmp.h +++ b/hmp.h @@ -107,5 +107,7 @@ void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str); void ringbuf_read_completion(ReadLineState *rs, int nb_args, const char *str); void watchdog_action_completion(ReadLineState *rs, int nb_args, const char *str); +void migrate_set_capability_completion(ReadLineState *rs, int nb_args, + const char *str); #endif diff --git a/monitor.c b/monitor.c index cb1fb7c..2974a66 100644 --- a/monitor.c +++ b/monitor.c @@ -4584,6 +4584,27 @@ void watchdog_action_completion(ReadLineState *rs, int nb_args, const char *str) add_completion_option(rs, str, none); } +void migrate_set_capability_completion(ReadLineState *rs, int nb_args, + const char *str) +{ +size_t len; + +len = strlen(str); +readline_set_completion_index(rs, len); +if (nb_args == 2) { +int i; +for (i = 0; i MIGRATION_CAPABILITY_MAX; i++) { +const char *name = MigrationCapability_lookup[i]; +if (!strncmp(str, name, len)) { +readline_add_completion(rs, name); +} +} +} else if (nb_args == 3) { +add_completion_option(rs, str, on); +add_completion_option(rs, str, off); +} +} + static void monitor_find_completion_by_table(Monitor *mon, const mon_cmd_t *cmd_table, char **args, -- 1.8.3.2
[Qemu-devel] [PATCH v2 02/17] monitor: Add command_completion callback to mon_cmd_t.
Convert object_add and object_del commands to use the new callback. Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 2 ++ hmp.h | 3 +++ monitor.c | 19 +-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 6bf4797..1b382b6 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1254,6 +1254,7 @@ ETEXI .params = [qom-type=]type,id=str[,prop=value][,...], .help = create QOM object, .mhandler.cmd = hmp_object_add, +.command_completion = object_add_completion, }, STEXI @@ -1268,6 +1269,7 @@ ETEXI .params = id, .help = destroy QOM object, .mhandler.cmd = hmp_object_del, +.command_completion = object_del_completion, }, STEXI diff --git a/hmp.h b/hmp.h index ed58f0e..2f2c059 100644 --- a/hmp.h +++ b/hmp.h @@ -15,6 +15,7 @@ #define HMP_H #include qemu-common.h +#include qemu/readline.h #include qapi-types.h #include qapi/qmp/qdict.h @@ -92,5 +93,7 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict); void hmp_cpu_add(Monitor *mon, const QDict *qdict); void hmp_object_add(Monitor *mon, const QDict *qdict); void hmp_object_del(Monitor *mon, const QDict *qdict); +void object_add_completion(ReadLineState *rs, int nb_args, const char *str); +void object_del_completion(ReadLineState *rs, int nb_args, const char *str); #endif diff --git a/monitor.c b/monitor.c index 342e83b..566a83f 100644 --- a/monitor.c +++ b/monitor.c @@ -137,6 +137,7 @@ typedef struct mon_cmd_t { * used, and mhandler of 1st level plays the role of help function. */ struct mon_cmd_t *sub_table; +void (*command_completion)(ReadLineState *rs, int nb_args, const char *str); } mon_cmd_t; /* file descriptors passed via SCM_RIGHTS */ @@ -4298,11 +4299,15 @@ static void device_add_completion(ReadLineState *rs, const char *str) g_slist_free(list); } -static void object_add_completion(ReadLineState *rs, const char *str) +void object_add_completion(ReadLineState *rs, int nb_args, const char *str) { GSList *list, *elt; size_t len; +if (nb_args != 2) { +return; +} + len = strlen(str); readline_set_completion_index(rs, len); list = elt = object_class_get_list(TYPE_USER_CREATABLE, false); @@ -4337,11 +4342,14 @@ static void device_del_completion(ReadLineState *rs, BusState *bus, } } -static void object_del_completion(ReadLineState *rs, const char *str) +void object_del_completion(ReadLineState *rs, int nb_args, const char *str) { ObjectPropertyInfoList *list, *start; size_t len; +if (nb_args != 2) { +return; +} len = strlen(str); readline_set_completion_index(rs, len); @@ -4395,6 +4403,9 @@ static void monitor_find_completion_by_table(Monitor *mon, return monitor_find_completion_by_table(mon, cmd-sub_table, args[1], nb_args - 1); } +if (cmd-command_completion) { +return cmd-command_completion(mon-rs, nb_args, args[nb_args - 1]); +} ptype = next_arg_type(cmd-args_type); for(i = 0; i nb_args - 2; i++) { @@ -4424,8 +4435,6 @@ static void monitor_find_completion_by_table(Monitor *mon, case 'O': if (!strcmp(cmd-name, device_add) nb_args == 2) { device_add_completion(mon-rs, str); -} else if (!strcmp(cmd-name, object_add) nb_args == 2) { -object_add_completion(mon-rs, str); } break; case 's': @@ -4445,8 +4454,6 @@ static void monitor_find_completion_by_table(Monitor *mon, size_t len = strlen(str); readline_set_completion_index(mon-rs, len); device_del_completion(mon-rs, sysbus_get_default(), str, len); -} else if (!strcmp(cmd-name, object_del) nb_args == 2) { -object_del_completion(mon-rs, str); } break; default: -- 1.8.3.2
[Qemu-devel] [PATCH v2 03/17] monitor: Add device_add and device_del completion.
Signed-off-by: Hani Benhabiles h...@linux.com --- hmp-commands.hx | 2 ++ hmp.h | 2 ++ monitor.c | 34 +- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 1b382b6..4c4d261 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -658,6 +658,7 @@ ETEXI .help = add device, like -device on the command line, .user_print = monitor_user_noop, .mhandler.cmd_new = do_device_add, +.command_completion = device_add_completion, }, STEXI @@ -673,6 +674,7 @@ ETEXI .params = device, .help = remove device, .mhandler.cmd = hmp_device_del, +.command_completion = device_del_completion, }, STEXI diff --git a/hmp.h b/hmp.h index 2f2c059..20ef454 100644 --- a/hmp.h +++ b/hmp.h @@ -95,5 +95,7 @@ void hmp_object_add(Monitor *mon, const QDict *qdict); void hmp_object_del(Monitor *mon, const QDict *qdict); void object_add_completion(ReadLineState *rs, int nb_args, const char *str); void object_del_completion(ReadLineState *rs, int nb_args, const char *str); +void device_add_completion(ReadLineState *rs, int nb_args, const char *str); +void device_del_completion(ReadLineState *rs, int nb_args, const char *str); #endif diff --git a/monitor.c b/monitor.c index 566a83f..710ba25 100644 --- a/monitor.c +++ b/monitor.c @@ -4278,11 +4278,15 @@ static const char *next_arg_type(const char *typestr) return (p != NULL ? ++p : typestr); } -static void device_add_completion(ReadLineState *rs, const char *str) +void device_add_completion(ReadLineState *rs, int nb_args, const char *str) { GSList *list, *elt; size_t len; +if (nb_args != 2) { +return; +} + len = strlen(str); readline_set_completion_index(rs, len); list = elt = object_class_get_list(TYPE_DEVICE, false); @@ -4323,8 +4327,8 @@ void object_add_completion(ReadLineState *rs, int nb_args, const char *str) g_slist_free(list); } -static void device_del_completion(ReadLineState *rs, BusState *bus, - const char *str, size_t len) +static void device_del_bus_completion(ReadLineState *rs, BusState *bus, + const char *str, size_t len) { BusChild *kid; @@ -4337,11 +4341,24 @@ static void device_del_completion(ReadLineState *rs, BusState *bus, } QLIST_FOREACH(dev_child, dev-child_bus, sibling) { -device_del_completion(rs, dev_child, str, len); +device_del_bus_completion(rs, dev_child, str, len); } } } +void device_del_completion(ReadLineState *rs, int nb_args, const char *str) +{ +size_t len; + +if (nb_args != 2) { +return; +} + +len = strlen(str); +readline_set_completion_index(rs, len); +device_del_bus_completion(rs, sysbus_get_default(), str, len); +} + void object_del_completion(ReadLineState *rs, int nb_args, const char *str) { ObjectPropertyInfoList *list, *start; @@ -4432,11 +4449,6 @@ static void monitor_find_completion_by_table(Monitor *mon, readline_set_completion_index(mon-rs, strlen(str)); bdrv_iterate(block_completion_it, mbs); break; -case 'O': -if (!strcmp(cmd-name, device_add) nb_args == 2) { -device_add_completion(mon-rs, str); -} -break; case 's': case 'S': if (!strcmp(cmd-name, sendkey)) { @@ -4450,10 +4462,6 @@ static void monitor_find_completion_by_table(Monitor *mon, } else if (!strcmp(cmd-name, help|?)) { monitor_find_completion_by_table(mon, cmd_table, args[1], nb_args - 1); -} else if (!strcmp(cmd-name, device_del) nb_args == 2) { -size_t len = strlen(str); -readline_set_completion_index(mon-rs, len); -device_del_completion(mon-rs, sysbus_get_default(), str, len); } break; default: -- 1.8.3.2
[Qemu-devel] Guest bandwidth setting
Hi All, I am new to QEMU. I am implementing some functionality where in I need to set the bandwidth control for my guest vms.Please let me know how can I do it. I am looking into net/net.c file,I dint find any leads.I tried two ways. I am trying to find how to set virtual nics(in my case e1000) speed,I did not find any ways to do that. If I devide the packet into smaller packets in qemu_deliver_packet() function I am not able to transfer the other half of the packet. Please let me know how can I resolve this. Thanks in advance Pradeep
[Qemu-devel] qemu core dump when vnc client connect to VM, Is anyone has the similar problem, thanks!
Hi, I've been tring to use QEMU-1.5.0 and Libvirt-1.1.0 to run a VM, but this problem comes up. The VM's log by libvirtd is as follow, which is similar to link: https://bugzilla.redhat.com/show_bug.cgi?id=906735, And it seems difficult to reproduce. Is there anyone have ever encounter this problem, is it a known bug, any information will be appriciated. Vm'log : 2014-03-28 08:53:32.961+: starting up LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin QEMU_AUDIO_DRV=none /usr/bin/kvm -name CentOS-6.5-ZFW-05 -S -machine pc-i440fx-1.5,accel=kvm,usb=off,system=linux -m 10240 -smp 4,maxcpus=24,sockets=12,cores=2,threads=1 -uuid f2a44069-7ff4-4e8a-bfd4-3513ac663ce2 -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/CentOS-6.5-ZFW-05.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 -device usb-ehci,id=ehci,bus=pci.0,addr=0x4 -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x5 -drive file=/vms/share-data02/CentOS-6.5-ZFW-05.5-ZFW,if=none,id=drive-ide0-0-0,format=qcow2,cache=directsync -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 -drive if=none,id=drive-ide0-1-0,readonly=on,format=raw -device ide-cd,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0,bootindex=2 -netdev tap,fd=27,id=hostnet0 -device rtl8139,netdev=hostnet0,id=net0,mac=0c:da:41:1d:32:4e,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -chardev socket,id=charchannel0,path=/var/lib/libvirt/qemu/CentOS-6.5-ZFW-05.agent,server,nowait -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=org.qemu.guest_agent.0 -device usb-tablet,id=input0,bus=usb.0 -vnc 0.0.0.0:3 -device cirrus-vga,id=video0,bus=pci.0,addr=0x2 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6 Domain id=5 is tainted: high-privileges char device redirected to /dev/pts/2 (label charserial0) *** glibc detected *** /usr/bin/kvm: realloc(): invalid old size: 0x7f799408d110 *** === Backtrace: = /lib/x86_64-linux-gnu/libc.so.6(+0x7e626)[0x7f79b7b6c626] /lib/x86_64-linux-gnu/libc.so.6(+0x81917)[0x7f79b7b6f917] /lib/x86_64-linux-gnu/libc.so.6(realloc+0xee)[0x7f79b7b711fe] /usr/bin/kvm(+0x2a3c4c)[0x7f79ba153c4c] realloc_and_trace /lib/x86_64-linux-gnu/libglib-2.0.so.0(g_realloc+0x17)[0x7f79b97dbaf7] /usr/bin/kvm(+0x294ccd)[0x7f79ba144ccd] buffer_reserve /usr/bin/kvm(+0x2972cc)[0x7f79ba1472cc] vnc_write /usr/bin/kvm(+0x27f41d)[0x7f79ba12f41d] send_hextile_tile_32 /usr/bin/kvm(+0x27fda7)[0x7f79ba12fda7] vnc_hextile_send_framebuffer_update /usr/bin/kvm(+0x295869)[0x7f79ba145869] vnc_send_framebuffer_update /usr/bin/kvm(+0x290e23)[0x7f79ba140e23] vnc_worker_thread_loop /usr/bin/kvm(+0x291193)[0x7f79ba141193] vnc_worker_thread /lib/x86_64-linux-gnu/libpthread.so.0(+0x7e9a)[0x7f79b7eb2e9a] /lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7f79b7be04bd] === Memory map: 7f771000-7f799000 rw-p 00:00 0 .. 7f799c02c000-7f79a000 ---p 00:00 0 7f79a000-7f79a0046000 rw-p 00:00 0 7f79a0046000-7f79a400 ---p 00:00 0 7f79a41e9000-7f79a41fe000 r-xp 08:01 1308204 /lib/x86_64-linux-gnu/libgcc_s.so.1 7f79a41fe000-7f79a43fd000 ---p 00015000 08:01 1308204 /lib/x86_64-linux-gnu/libgcc_s.so.1 7f79a43fd000-7f79a43fe000 r--p 00014000 08:01 1308204 /lib/x86_64-linux-gnu/libgcc_s.so.1 7f79a43fe000-7f79a43ff000 rw-p 00015000 08:01 1308204 /lib/x86_64-linux-gnu/libgcc_s.so.1 7f79a43ff000-7f79a440 ---p 00:00 0 7f79a440-7f79a4c0 rw-p 00:00 0 [stack:44019] .. 7f79a5dfa000-7f79a5dfb000 ---p 00:00 0 7f79a5dfb000-7f79a65fb000 rw-p 00:00 0 [stack:44013] 7f79a65fb000-7f79a65fc000 ---p 00:00 0 7f79a65fc000-7f79a6dfc000 rw-p 00:00 0 [stack:44012] 7f79a6dfc000-7f79a6dfd000 ---p 00:00 0 7f79a6dfd000-7f79a75fd000 rw-p 00:00 0 [stack:44011] 7f79a75fd000-7f79a75fe000 ---p 00:00 0 7f79a75fe000-7f79ac00 rw-p 00:00 0 [stack:44010] 7f79ac00-7f79ac021000 rw-p 00:00 0 ... 7f79b2a95000-7f79b3295000 rw-p 00:00 0 [stack:44009] 7f79b3295000-7f79b32a1000 r-xp 08:01 1308191 /lib/x86_64-linux-gnu/libnss_files-2.15.so 7f79b32a1000-7f79b34a ---p c000 08:01 1308191 /lib/x86_64-linux-gnu/libnss_files-2.15.so 7f79b34a-7f79b34a1000 r--p b000 08:01 1308191 /lib/x86_64-linux-gnu/libnss_files-2.15.so 7f79b34a1000-7f79b34a2000 rw-p c000 08:01 1308191
[Qemu-devel] [PATCH] input: mouse_set should check input device type.
Otherwise, the index of an input device like a usb-kbd is silently accepted. (qemu) info mice Mouse #2: QEMU PS/2 Mouse * Mouse #3: QEMU HID Mouse (qemu) mouse_set 1 (qemu) info mice Mouse #2: QEMU PS/2 Mouse * Mouse #3: QEMU HID Mouse Signed-off-by: Hani Benhabiles h...@linux.com --- ui/input.c | 15 +++ 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/ui/input.c b/ui/input.c index 2761911..013de95 100644 --- a/ui/input.c +++ b/ui/input.c @@ -342,11 +342,18 @@ void do_mouse_set(Monitor *mon, const QDict *qdict) int found = 0; QTAILQ_FOREACH(s, handlers, node) { -if (s-id == index) { -found = 1; -qemu_input_handler_activate(s); -break; +if (s-id != index) { +continue; } +if (!(s-handler-mask (INPUT_EVENT_MASK_REL | + INPUT_EVENT_MASK_ABS))) { +monitor_printf(mon, Input device '%s' is not a mouse, + s-handler-name); +return; +} +found = 1; +qemu_input_handler_activate(s); +break; } if (!found) { -- 1.8.3.2
[Qemu-devel] [PATCH trival] vl.c: clean up code
in get_boot_device() - remove 'res' to simplify code in main(): - remove useless 'continue'. - in main switch(): - remove or adjust all useless 'break'. - remove useless '{' and '}'. - use assignment directly to replace useless 'args' (which is defined in the middle of code block). Signed-off-by: Chen Gang gang.chen.5...@gmail.com --- vl.c | 36 +--- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/vl.c b/vl.c index 9975e5a..9c733cb 100644 --- a/vl.c +++ b/vl.c @@ -1188,18 +1188,16 @@ DeviceState *get_boot_device(uint32_t position) { uint32_t counter = 0; FWBootEntry *i = NULL; -DeviceState *res = NULL; if (!QTAILQ_EMPTY(fw_boot_order)) { QTAILQ_FOREACH(i, fw_boot_order, link) { if (counter == position) { -res = i-dev; -break; +return i-dev; } counter++; } } -return res; +return NULL; } /* @@ -3034,7 +3032,6 @@ int main(int argc, char **argv, char **envp) if (argv[optind][0] != '-') { /* disk image */ optind++; -continue; } else { const QEMUOption *popt; @@ -3204,11 +3201,11 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_curses: #ifdef CONFIG_CURSES display_type = DT_CURSES; +break; #else fprintf(stderr, Curses support is disabled\n); exit(1); #endif -break; case QEMU_OPTION_portrait: graphic_rotate = 90; break; @@ -3286,7 +3283,6 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_audio_help: AUD_help (); exit (0); -break; case QEMU_OPTION_soundhw: select_soundhw (optarg); break; @@ -3296,7 +3292,6 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_version: version(); exit(0); -break; case QEMU_OPTION_m: { int64_t value; uint64_t sz; @@ -3638,11 +3633,10 @@ int main(int argc, char **argv, char **envp) olist = qemu_find_opts(machine); qemu_opts_parse(olist, accel=tcg, 0); break; -case QEMU_OPTION_no_kvm_pit: { +case QEMU_OPTION_no_kvm_pit: fprintf(stderr, Warning: KVM PIT can no longer be disabled separately.\n); break; -} case QEMU_OPTION_no_kvm_pit_reinjection: { static GlobalProperty kvm_pit_lost_tick_policy[] = { { @@ -3681,11 +3675,11 @@ int main(int argc, char **argv, char **envp) #ifdef CONFIG_VNC display_remote++; vnc_display = optarg; +break; #else fprintf(stderr, VNC support is disabled\n); exit(1); #endif -break; case QEMU_OPTION_no_acpi: acpi_enabled = 0; break; @@ -3811,7 +3805,6 @@ int main(int argc, char **argv, char **envp) xen_mode = XEN_ATTACH; break; case QEMU_OPTION_trace: -{ opts = qemu_opts_parse(qemu_find_opts(trace), optarg, 0); if (!opts) { exit(1); @@ -3819,7 +3812,6 @@ int main(int argc, char **argv, char **envp) trace_events = qemu_opt_get(opts, events); trace_file = qemu_opt_get(opts, file); break; -} case QEMU_OPTION_readconfig: { int ret = qemu_read_config_file(optarg); @@ -3876,12 +3868,12 @@ int main(int argc, char **argv, char **envp) if (!opts) { exit(1); } +break; #else error_report(File descriptor passing is disabled on this platform); exit(1); #endif -break; case QEMU_OPTION_object: opts = qemu_opts_parse(qemu_find_opts(object), optarg, 1); if (!opts) { @@ -4371,15 +4363,13 @@ int main(int argc, char **argv, char **envp) qdev_machine_init(); -QEMUMachineInitArgs args = { .machine = machine, - .ram_size = ram_size, - .boot_order = boot_order, - .kernel_filename = kernel_filename, - .kernel_cmdline = kernel_cmdline, - .initrd_filename = initrd_filename, - .cpu_model = cpu_model }; - -current_machine-init_args =
Re: [Qemu-devel] [PATCH trival] vl.c: clean up code
Hello Maintainers: In main switch of main(), it contents several styles for {...} code block. If it is necessary to use unique style within a function, please let me know, I will/should clean up it. And also better to tell me which style we need choose -- for me, I don't know which style is the best to Qemu. Thanks. On 03/30/2014 10:34 PM, Chen Gang wrote: in get_boot_device() - remove 'res' to simplify code in main(): - remove useless 'continue'. - in main switch(): - remove or adjust all useless 'break'. - remove useless '{' and '}'. - use assignment directly to replace useless 'args' (which is defined in the middle of code block). Signed-off-by: Chen Gang gang.chen.5...@gmail.com --- vl.c | 36 +--- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/vl.c b/vl.c index 9975e5a..9c733cb 100644 --- a/vl.c +++ b/vl.c @@ -1188,18 +1188,16 @@ DeviceState *get_boot_device(uint32_t position) { uint32_t counter = 0; FWBootEntry *i = NULL; -DeviceState *res = NULL; if (!QTAILQ_EMPTY(fw_boot_order)) { QTAILQ_FOREACH(i, fw_boot_order, link) { if (counter == position) { -res = i-dev; -break; +return i-dev; } counter++; } } -return res; +return NULL; } /* @@ -3034,7 +3032,6 @@ int main(int argc, char **argv, char **envp) if (argv[optind][0] != '-') { /* disk image */ optind++; -continue; } else { const QEMUOption *popt; @@ -3204,11 +3201,11 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_curses: #ifdef CONFIG_CURSES display_type = DT_CURSES; +break; #else fprintf(stderr, Curses support is disabled\n); exit(1); #endif -break; case QEMU_OPTION_portrait: graphic_rotate = 90; break; @@ -3286,7 +3283,6 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_audio_help: AUD_help (); exit (0); -break; case QEMU_OPTION_soundhw: select_soundhw (optarg); break; @@ -3296,7 +3292,6 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_version: version(); exit(0); -break; case QEMU_OPTION_m: { int64_t value; uint64_t sz; @@ -3638,11 +3633,10 @@ int main(int argc, char **argv, char **envp) olist = qemu_find_opts(machine); qemu_opts_parse(olist, accel=tcg, 0); break; -case QEMU_OPTION_no_kvm_pit: { +case QEMU_OPTION_no_kvm_pit: fprintf(stderr, Warning: KVM PIT can no longer be disabled separately.\n); break; -} case QEMU_OPTION_no_kvm_pit_reinjection: { static GlobalProperty kvm_pit_lost_tick_policy[] = { { @@ -3681,11 +3675,11 @@ int main(int argc, char **argv, char **envp) #ifdef CONFIG_VNC display_remote++; vnc_display = optarg; +break; #else fprintf(stderr, VNC support is disabled\n); exit(1); #endif -break; case QEMU_OPTION_no_acpi: acpi_enabled = 0; break; @@ -3811,7 +3805,6 @@ int main(int argc, char **argv, char **envp) xen_mode = XEN_ATTACH; break; case QEMU_OPTION_trace: -{ opts = qemu_opts_parse(qemu_find_opts(trace), optarg, 0); if (!opts) { exit(1); @@ -3819,7 +3812,6 @@ int main(int argc, char **argv, char **envp) trace_events = qemu_opt_get(opts, events); trace_file = qemu_opt_get(opts, file); break; -} case QEMU_OPTION_readconfig: { int ret = qemu_read_config_file(optarg); @@ -3876,12 +3868,12 @@ int main(int argc, char **argv, char **envp) if (!opts) { exit(1); } +break; #else error_report(File descriptor passing is disabled on this platform); exit(1); #endif -break; case QEMU_OPTION_object: opts = qemu_opts_parse(qemu_find_opts(object), optarg, 1); if (!opts) { @@ -4371,15 +4363,13 @@ int main(int argc, char **argv, char
Re: [Qemu-devel] [PATCH] vl.c: use 'break' instead of 'continue' in configure_accelerator()
Hello Maintainers: If it is necessary to send patch v2 by me, please let me know, I will/should send. Thanks. On 03/27/2014 06:01 PM, Chen Gang wrote: On 03/27/2014 04:59 PM, Markus Armbruster wrote: Chen Gang gang.chen.5...@gmail.com writes: At present, each 'opt_name' of 'accel_list' is uniq with each other, so 'buf' can only match one 'opt_name'. When drop into the matching code block, can 'break' outside related 'for' looping after finish processing it (just like the other 'break' within the matching block). After print ... not support for this target, it can avoid to print ... accelerator does not exist. Signed-off-by: Chen Gang gang.chen.5...@gmail.com --- vl.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vl.c b/vl.c index 842e897..b4f98fa 100644 --- a/vl.c +++ b/vl.c @@ -2709,7 +2709,7 @@ static int configure_accelerator(QEMUMachine *machine) if (!accel_list[i].available()) { printf(%s not supported for this target\n, accel_list[i].name); -continue; +break; } *(accel_list[i].allowed) = true; ret = accel_list[i].init(machine); Works, because the opt_name in accel_list[] are distinct, as you explained in your commit message. Apropos commit message. You first explain what you do, and only then state the problem you're trying to solve. That's backwards. Start with the problem. Only then explain your solution, if it needs explaining. This one, I think, doesn't. Suggested commit message: vl: Report accelerator not supported for target more nicely When you ask for an accelerator not supported for your target, you get a bogus accelerator does not exist message: $ qemu-system-arm -machine none,accel=kvm KVM not supported for this target kvm accelerator does not exist. No accelerator found! Suppress it. Thank you for your details, that sounds reasonable to me. Next, I will/should notice start with the issue, and then explain the solution. Thanks. -- Chen Gang Open, share and attitude like air, water and life which God blessed
Re: [Qemu-devel] [PATCH 0/8] tcg: tidy the type of code_ptr
On 03/29/2014 01:26 PM, Peter Maydell wrote: It seems like it might be worth abstracting out give me the byte difference between these two code pointers rather than having inline (uintptr_t)codeptr1 - (uintptr_t)codeptr2, but I dunno. Yeah, I dithered about that. I couldn't come up with a good name that adequately described what I wanted that was really any shorter than just having the casts. Is there a better name than 'tcg_itype' ? Putting 'type' in the name of a type is a bit redundant, and suggests it contains a type rather than an insn. I'm open to suggestions there as well. On x86 and ia64, it won't hold an entire insn, so tcg_insn seemed inappropriate. r~
[Qemu-devel] 2.0 regression: loadvm assertion with ehci + tablet
With git master, loadvm hits an assert failure if using ehci and usb tablet. Steps to reproduce: $ qemu-img create -f qcow2 foo.qcow2 10G $ ./x86_64-softmmu/qemu-system-x86_64 \ -enable-kvm -m 4096 \ -device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x5.0x7 \ -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x5 \ -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x5.0x1 \ -device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x5.0x2 \ -device usb-tablet,id=input0 \ -hda foo.qcow2 \ -cdrom Fedora-20-x86_64-Live-Desktop.iso \ -boot d -monitor stdio wait until guest boot to 'welcome to fedora' window (qemu) savevm foo (qemu) loadvm foo qemu-system-x86_64: hw/pci/pci.c:250: pcibus_reset: Assertion `bus-irq_count[i] == 0' failed. The relevant backtrace bits for the assertion: #4 0x7f8f7241971e in pcibus_reset (qbus=0x7f8f74082fd0) at hw/pci/pci.c:250 #5 0x7f8f723bd36d in qbus_reset_one (bus=0x7f8f74082fd0, opaque=optimized out) at hw/core/qdev.c:249 #6 0x7f8f723bec88 in qdev_walk_children (dev=0x7f8f73efb320, pre_devfn=0x0, pre_busfn=0x0, post_devfn=0x7f8f723bf4f0 qdev_reset_one, post_busfn=0x7f8f723bd320 qbus_reset_one, opaque=0x0) at hw/core/qdev.c:403 #7 0x7f8f723bedb8 in qbus_walk_children (bus=0x7f8f740706e0, pre_devfn=0x0, pre_busfn=0x0, post_devfn=0x7f8f723bf4f0 qdev_reset_one, post_busfn=0x7f8f723bd320 qbus_reset_one, opaque=0x0) at hw/core/qdev.c:369 #8 0x7f8f724f5c5d in qemu_devices_reset () at vl.c:1867 #9 qemu_system_reset (report=report@entry=false) at vl.c:1880 #10 0x7f8f7256dba2 in load_vmstate (name=name@entry=0x7f8f7417a160 foo) at /home/crobinso/src/qemu/savevm.c:1098 The 'cause' is this: #0 ehci_detach (port=0x56436968) at hw/usb/hcd-ehci.c:810 #1 0x55727b5e in usb_detach (port=port@entry=0x56436968) at hw/usb/core.c:49 #2 0x55736bf3 in ehci_reset (opaque=0x564364d8) at hw/usb/hcd-ehci.c:941 #3 0x557e1fcd in qemu_devices_reset () at vl.c:1867 #4 qemu_system_reset (report=report@entry=false) at vl.c:1880 #5 0x55859f12 in load_vmstate (name=name@entry=0x56458210 foo) at /home/crobinso/src/qemu/savevm.c:1098 ehci_reset calls usb_detach which sets pcibus-irq_count[3] = 1. pcibus_reset runs and hits the assertion. But I don't understand this stuff enough to determine what's actually wrong here :) I bisected the issue to: commit 31b030d4abc5bea89c2b33b39d3b302836f6b6ee Author: Andreas Färber afaer...@suse.de Date: Wed Sep 4 01:29:02 2013 +0200 cputlb: Change tlb_flush_page() argument to CPUState Signed-off-by: Andreas Färber afaer...@suse.de ...and then I double checked it since that sounds unrelated. Same result. Thanks, Cole
[Qemu-devel] [PATCHv50/3] qapi: Allow modularization of QAPI schema files
Adds an include primitive to the syntax of QAPI schema files, allowing these to be modularized into multiple per-topic files in the future. Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- Changes in v5: * Rebase on b3706fa. * Remove 'error_base' argument in 'parse_schema'; fix test checks instead. * Implement include directive using JSON syntax. Changes in v4: * Rebase on 3e890c7. * Minor cosmetic changes. * Fix recording of included files in case of a cycle error. * Add a more complex include cycle test. Changes in v3: * Fix documentation examples regarding how the input file is passed to the scripts. * Add documentation for the 'include' directive. * Detect inclusion loops. * Fix tests/qapi-schema/test-qapi.py and tests/Makefile to use an explicit input file when running tests. * Fix QAPI tests to cope with an explicit input file. * Add tests for the include directive. Changes in v2: * Change the scripts to use an explicit input file instead of standard input. * Fix tests/Makefile to use the new argument. * Get the input directory for the include directive from the input file dirname. Lluís Vilanova (3): qapi: Use an explicit input file qapi: Add a primitive to include other files from a QAPI schema file qapi: Add tests for the include directive Makefile | 24 +--- docs/qapi-code-gen.txt | 11 +- scripts/qapi-commands.py | 10 - scripts/qapi-types.py |9 +++-- scripts/qapi-visit.py |9 +++-- scripts/qapi.py| 40 +--- tests/Makefile | 19 +++--- tests/qapi-schema/duplicate-key.err|2 + .../qapi-schema/flat-union-invalid-branch-key.err |2 + .../flat-union-invalid-discriminator.err |2 + tests/qapi-schema/flat-union-no-base.err |2 + .../flat-union-string-discriminator.err|2 + tests/qapi-schema/funny-char.err |2 + tests/qapi-schema/include-cycle-b.json |1 + tests/qapi-schema/include-cycle-c.json |1 + tests/qapi-schema/include-cycle.err|1 + tests/qapi-schema/include-cycle.exit |1 + tests/qapi-schema/include-cycle.json |1 + tests/qapi-schema/include-cycle.out|0 tests/qapi-schema/include-nested-err.err |1 + tests/qapi-schema/include-nested-err.exit |1 + tests/qapi-schema/include-nested-err.json |1 + tests/qapi-schema/include-nested-err.out |0 tests/qapi-schema/include-no-file.err |1 + tests/qapi-schema/include-no-file.exit |1 + tests/qapi-schema/include-no-file.json |1 + tests/qapi-schema/include-no-file.out |0 tests/qapi-schema/include-self-cycle.err |1 + tests/qapi-schema/include-self-cycle.exit |1 + tests/qapi-schema/include-self-cycle.json |1 + tests/qapi-schema/include-self-cycle.out |0 tests/qapi-schema/include-simple-sub.json |2 + tests/qapi-schema/include-simple.err |0 tests/qapi-schema/include-simple.exit |1 + tests/qapi-schema/include-simple.json |1 + tests/qapi-schema/include-simple.out |3 ++ tests/qapi-schema/missing-colon.err|2 + tests/qapi-schema/missing-comma-list.err |2 + tests/qapi-schema/missing-comma-object.err |2 + tests/qapi-schema/non-objects.err |2 + tests/qapi-schema/quoted-structural-chars.err |2 + tests/qapi-schema/test-qapi.py |3 +- tests/qapi-schema/trailing-comma-list.err |2 + tests/qapi-schema/trailing-comma-object.err|2 + tests/qapi-schema/unclosed-list.err|2 + tests/qapi-schema/unclosed-object.err |2 + tests/qapi-schema/unclosed-string.err |2 + tests/qapi-schema/union-invalid-base.err |2 + 48 files changed, 133 insertions(+), 47 deletions(-) create mode 100644 tests/qapi-schema/include-cycle-b.json create mode 100644 tests/qapi-schema/include-cycle-c.json create mode 100644 tests/qapi-schema/include-cycle.err create mode 100644 tests/qapi-schema/include-cycle.exit create mode 100644 tests/qapi-schema/include-cycle.json create mode 100644 tests/qapi-schema/include-cycle.out create mode 100644 tests/qapi-schema/include-nested-err.err create mode 100644 tests/qapi-schema/include-nested-err.exit create mode 100644 tests/qapi-schema/include-nested-err.json create mode 100644 tests/qapi-schema/include-nested-err.out create mode 100644 tests/qapi-schema/include-no-file.err
[Qemu-devel] [PATCHv51/3] qapi: Use an explicit input file
Use an explicit input file on the command-line instead of reading from standard input Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- Makefile | 24 +++- docs/qapi-code-gen.txt |4 ++- scripts/qapi-commands.py | 10 ++-- scripts/qapi-types.py |9 +--- scripts/qapi-visit.py |9 +--- scripts/qapi.py|5 +++- tests/Makefile | 15 + tests/qapi-schema/duplicate-key.err|2 +- .../qapi-schema/flat-union-invalid-branch-key.err |2 +- .../flat-union-invalid-discriminator.err |2 +- tests/qapi-schema/flat-union-no-base.err |2 +- .../flat-union-string-discriminator.err|2 +- tests/qapi-schema/funny-char.err |2 +- tests/qapi-schema/missing-colon.err|2 +- tests/qapi-schema/missing-comma-list.err |2 +- tests/qapi-schema/missing-comma-object.err |2 +- tests/qapi-schema/non-objects.err |2 +- tests/qapi-schema/quoted-structural-chars.err |2 +- tests/qapi-schema/test-qapi.py |3 ++- tests/qapi-schema/trailing-comma-list.err |2 +- tests/qapi-schema/trailing-comma-object.err|2 +- tests/qapi-schema/unclosed-list.err|2 +- tests/qapi-schema/unclosed-object.err |2 +- tests/qapi-schema/unclosed-string.err |2 +- tests/qapi-schema/union-invalid-base.err |2 +- 25 files changed, 72 insertions(+), 41 deletions(-) diff --git a/Makefile b/Makefile index ec74039..c7cec01 100644 --- a/Makefile +++ b/Makefile @@ -237,23 +237,35 @@ qapi-py = $(SRC_PATH)/scripts/qapi.py $(SRC_PATH)/scripts/ordereddict.py qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h :\ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o qga/qapi-generated -p qga- $, GEN $@) + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \ + $(gen-out-type) -i $ -o qga/qapi-generated -p qga-, \ + GEN $@) qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h :\ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o qga/qapi-generated -p qga- $, GEN $@) + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \ + $(gen-out-type) -i $ -o qga/qapi-generated -p qga-, \ + GEN $@) qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c :\ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o qga/qapi-generated -p qga- $, GEN $@) + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \ + $(gen-out-type) -i $ -o qga/qapi-generated -p qga-, \ + GEN $@) qapi-types.c qapi-types.h :\ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o . -b $, GEN $@) + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \ + $(gen-out-type) -i $ -o . -b, \ + GEN $@) qapi-visit.c qapi-visit.h :\ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o . -b $, GEN $@) + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \ + $(gen-out-type) -i $ -o . -b, \ + GEN $@) qmp-commands.h qmp-marshal.c :\ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o . $, GEN $@) + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \ + $(gen-out-type) -i $ -o . -m, \ + GEN $@) QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h) $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index d78921f..824f6e5 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -221,7 +221,7 @@ created code. Example: mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-types.py \ - --output-dir=qapi-generated --prefix=example- example-schema.json +
[Qemu-devel] [PATCHv52/3] qapi: Add a primitive to include other files from a QAPI schema file
Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- docs/qapi-code-gen.txt |7 +++ scripts/qapi.py| 35 ++- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index 824f6e5..1e19f64 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -40,6 +40,13 @@ enumeration types and union types. Generally speaking, types definitions should always use CamelCase for the type names. Command names should be all lower case with words separated by a hyphen. +The QAPI schema definitions can be modularized using the 'include' directive: + + { 'include': 'path/to/file.json'} + +Include paths are relative to the file using the directive. + + === Complex types === A complex type is a dictionary containing a single key whose value is a diff --git a/scripts/qapi.py b/scripts/qapi.py index 3a38e27..f6e16ff 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -11,6 +11,8 @@ # This work is licensed under the terms of the GNU GPL, version 2. # See the COPYING file in the top-level directory. +import os +import re from ordereddict import OrderedDict import os import sys @@ -62,8 +64,11 @@ class QAPIExprError(Exception): class QAPISchema: -def __init__(self, fp): +def __init__(self, fp, included=[]): self.fp = fp +input_path = os.path.abspath(fp.name) +self.included = included + [input_path] +self.input_dir = os.path.dirname(input_path) self.src = fp.read() if self.src == '' or self.src[-1] != '\n': self.src += '\n' @@ -75,9 +80,29 @@ class QAPISchema: while self.tok != None: expr_info = {'fp': fp, 'line': self.line} -expr_elem = {'expr': self.get_expr(False), - 'info': expr_info} -self.exprs.append(expr_elem) +expr = self.get_expr(False) +if isinstance(expr, dict) and include in expr: +if len(expr) != 1: +raise QAPIExprError(expr_info, Invalid 'include' directive) +include_path = expr[include] +if not os.path.isabs(include_path): +include_path = os.path.join(self.input_dir, include_path) +if not os.path.isfile(include_path): +raise QAPIExprError( +expr_info, +'Non-existing included file %s' % +include_path) +if include_path in self.included: +raise QAPIExprError(expr_info, Infinite inclusion loop: %s +% - .join(self.included + + [include_path])) +exprs_include = QAPISchema(open(include_path, r), + self.included) +self.exprs.extend(exprs_include.exprs) +else: +expr_elem = {'expr': expr, + 'info': expr_info} +self.exprs.append(expr_elem) def accept(self): while True: @@ -267,7 +292,7 @@ def check_exprs(schema): def parse_schema(input_path): try: schema = QAPISchema(open(input_path, r)) -except QAPISchemaError, e: +except (QAPISchemaError, QAPIExprError), e: print sys.stderr, e exit(1)
[Qemu-devel] [PATCHv53/3] qapi: Add tests for the include directive
Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- tests/Makefile|4 +++- tests/qapi-schema/include-cycle-b.json|1 + tests/qapi-schema/include-cycle-c.json|1 + tests/qapi-schema/include-cycle.err |1 + tests/qapi-schema/include-cycle.exit |1 + tests/qapi-schema/include-cycle.json |1 + tests/qapi-schema/include-cycle.out |0 tests/qapi-schema/include-nested-err.err |1 + tests/qapi-schema/include-nested-err.exit |1 + tests/qapi-schema/include-nested-err.json |1 + tests/qapi-schema/include-nested-err.out |0 tests/qapi-schema/include-no-file.err |1 + tests/qapi-schema/include-no-file.exit|1 + tests/qapi-schema/include-no-file.json|1 + tests/qapi-schema/include-no-file.out |0 tests/qapi-schema/include-self-cycle.err |1 + tests/qapi-schema/include-self-cycle.exit |1 + tests/qapi-schema/include-self-cycle.json |1 + tests/qapi-schema/include-self-cycle.out |0 tests/qapi-schema/include-simple-sub.json |2 ++ tests/qapi-schema/include-simple.err |0 tests/qapi-schema/include-simple.exit |1 + tests/qapi-schema/include-simple.json |1 + tests/qapi-schema/include-simple.out |3 +++ 24 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/qapi-schema/include-cycle-b.json create mode 100644 tests/qapi-schema/include-cycle-c.json create mode 100644 tests/qapi-schema/include-cycle.err create mode 100644 tests/qapi-schema/include-cycle.exit create mode 100644 tests/qapi-schema/include-cycle.json create mode 100644 tests/qapi-schema/include-cycle.out create mode 100644 tests/qapi-schema/include-nested-err.err create mode 100644 tests/qapi-schema/include-nested-err.exit create mode 100644 tests/qapi-schema/include-nested-err.json create mode 100644 tests/qapi-schema/include-nested-err.out create mode 100644 tests/qapi-schema/include-no-file.err create mode 100644 tests/qapi-schema/include-no-file.exit create mode 100644 tests/qapi-schema/include-no-file.json create mode 100644 tests/qapi-schema/include-no-file.out create mode 100644 tests/qapi-schema/include-self-cycle.err create mode 100644 tests/qapi-schema/include-self-cycle.exit create mode 100644 tests/qapi-schema/include-self-cycle.json create mode 100644 tests/qapi-schema/include-self-cycle.out create mode 100644 tests/qapi-schema/include-simple-sub.json create mode 100644 tests/qapi-schema/include-simple.err create mode 100644 tests/qapi-schema/include-simple.exit create mode 100644 tests/qapi-schema/include-simple.json create mode 100644 tests/qapi-schema/include-simple.out diff --git a/tests/Makefile b/tests/Makefile index f2beb1b..4f9857c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -164,7 +164,9 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \ duplicate-key.json union-invalid-base.json flat-union-no-base.json \ flat-union-invalid-discriminator.json \ flat-union-invalid-branch-key.json flat-union-reverse-define.json \ -flat-union-string-discriminator.json) +flat-union-string-discriminator.json \ +include-simple.json include-nested-err.json include-no-file.json \ +include-self-cycle.json include-cycle.json) GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h diff --git a/tests/qapi-schema/include-cycle-b.json b/tests/qapi-schema/include-cycle-b.json new file mode 100644 index 000..4fa985d --- /dev/null +++ b/tests/qapi-schema/include-cycle-b.json @@ -0,0 +1 @@ +{ 'include': 'include-cycle-c.json' } diff --git a/tests/qapi-schema/include-cycle-c.json b/tests/qapi-schema/include-cycle-c.json new file mode 100644 index 000..d12b592 --- /dev/null +++ b/tests/qapi-schema/include-cycle-c.json @@ -0,0 +1 @@ +{ 'include': 'include-cycle.json' } diff --git a/tests/qapi-schema/include-cycle.err b/tests/qapi-schema/include-cycle.err new file mode 100644 index 000..7a74655 --- /dev/null +++ b/tests/qapi-schema/include-cycle.err @@ -0,0 +1 @@ +tests/qapi-schema/include-cycle-c.json:1: Infinite inclusion loop: tests/qapi-schema/include-cycle.json - tests/qapi-schema/include-cycle-b.json - tests/qapi-schema/include-cycle-c.json - tests/qapi-schema/include-cycle.json diff --git a/tests/qapi-schema/include-cycle.exit b/tests/qapi-schema/include-cycle.exit new file mode 100644 index 000..d00491f --- /dev/null +++ b/tests/qapi-schema/include-cycle.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/include-cycle.json b/tests/qapi-schema/include-cycle.json new file mode 100644 index 000..6fcf1eb --- /dev/null +++ b/tests/qapi-schema/include-cycle.json @@ -0,0 +1 @@ +{ 'include': 'include-cycle-b.json' } diff --git a/tests/qapi-schema/include-cycle.out b/tests/qapi-schema/include-cycle.out new file mode 100644 index 000..e69de29 diff --git
Re: [Qemu-devel] 2.0 regression: loadvm assertion with ehci + tablet
On Sun, Mar 30, 2014 at 04:27:33PM -0400, Cole Robinson wrote: With git master, loadvm hits an assert failure if using ehci and usb tablet. Steps to reproduce: $ qemu-img create -f qcow2 foo.qcow2 10G $ ./x86_64-softmmu/qemu-system-x86_64 \ -enable-kvm -m 4096 \ -device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x5.0x7 \ -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x5 \ -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x5.0x1 \ -device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x5.0x2 \ -device usb-tablet,id=input0 \ -hda foo.qcow2 \ -cdrom Fedora-20-x86_64-Live-Desktop.iso \ -boot d -monitor stdio wait until guest boot to 'welcome to fedora' window (qemu) savevm foo (qemu) loadvm foo qemu-system-x86_64: hw/pci/pci.c:250: pcibus_reset: Assertion `bus-irq_count[i] == 0' failed. The relevant backtrace bits for the assertion: #4 0x7f8f7241971e in pcibus_reset (qbus=0x7f8f74082fd0) at hw/pci/pci.c:250 #5 0x7f8f723bd36d in qbus_reset_one (bus=0x7f8f74082fd0, opaque=optimized out) at hw/core/qdev.c:249 #6 0x7f8f723bec88 in qdev_walk_children (dev=0x7f8f73efb320, pre_devfn=0x0, pre_busfn=0x0, post_devfn=0x7f8f723bf4f0 qdev_reset_one, post_busfn=0x7f8f723bd320 qbus_reset_one, opaque=0x0) at hw/core/qdev.c:403 #7 0x7f8f723bedb8 in qbus_walk_children (bus=0x7f8f740706e0, pre_devfn=0x0, pre_busfn=0x0, post_devfn=0x7f8f723bf4f0 qdev_reset_one, post_busfn=0x7f8f723bd320 qbus_reset_one, opaque=0x0) at hw/core/qdev.c:369 #8 0x7f8f724f5c5d in qemu_devices_reset () at vl.c:1867 #9 qemu_system_reset (report=report@entry=false) at vl.c:1880 #10 0x7f8f7256dba2 in load_vmstate (name=name@entry=0x7f8f7417a160 foo) at /home/crobinso/src/qemu/savevm.c:1098 The 'cause' is this: #0 ehci_detach (port=0x56436968) at hw/usb/hcd-ehci.c:810 #1 0x55727b5e in usb_detach (port=port@entry=0x56436968) at hw/usb/core.c:49 #2 0x55736bf3 in ehci_reset (opaque=0x564364d8) at hw/usb/hcd-ehci.c:941 #3 0x557e1fcd in qemu_devices_reset () at vl.c:1867 #4 qemu_system_reset (report=report@entry=false) at vl.c:1880 #5 0x55859f12 in load_vmstate (name=name@entry=0x56458210 foo) at /home/crobinso/src/qemu/savevm.c:1098 ehci_reset calls usb_detach which sets pcibus-irq_count[3] = 1. pcibus_reset runs and hits the assertion. But I don't understand this stuff enough to determine what's actually wrong here :) I bisected the issue to: commit 31b030d4abc5bea89c2b33b39d3b302836f6b6ee Author: Andreas Färber afaer...@suse.de Date: Wed Sep 4 01:29:02 2013 +0200 cputlb: Change tlb_flush_page() argument to CPUState Signed-off-by: Andreas Färber afaer...@suse.de ...and then I double checked it since that sounds unrelated. Same result. Thanks, Cole Looking for related stuff in pci, try this one: qdev: switch reset to post-order
[Qemu-devel] Qemu and access to guest memory
Hello, I'm trying to write my own driver for eepro100 (e100) NIC for Linux 2.6.3x running on Qemu 1.7.90. Unfortunately I've got problems with accessing memory. In my e100 driver I set some memory area to configure e100 Control Block. I set appropriate offset address to point to this control block (using Load CU Base command and CU Start), but seems like qemu e100 driver emulator can't see this control block. Qemu e100 emulator sees just only 0...0 instead of my control block data. I dig a little the qemu sources and seems like pci_dma_read() from read_cb() returns only 0 instead of my data. It causes the e100 emulator to run indefinitely action_command() and hung up the whole qemu. I'd like to ask - how can I debug qemu and get access to guest OS memory and verify that my data really there are under desired address? Under Linux I allocate memory with kmalloc() and obtain physical address with virt_to_phys() function. GDB connected to qemu tells, that there are my data under given address - so why qemu don't see them?
[Qemu-devel] [Bug 1299858] [NEW] qemu all apps crash on OS X 10.6.8
Public bug reported: qemu-2.0.0-rc0 (and 1.7.1) crashes with SIGABORT in all apps when configured with --with-coroutine=sigaltstack (which is what configure selects by default) but all run fine if configured with --with- coroutine=gthread. Crash is at line 253 (last line of Coroutine *qemu_coroutine_new(void)) in coroutine-sigaltstack.c in 2.0.0-rc0 tarball. Platform is OS X 10.6.8 (Darwin Kernel Version 10.8.0), compiler gcc 4.2.1 Sorry for the sparse report but I'm short on time today. ** Affects: qemu Importance: Undecided Status: New -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1299858 Title: qemu all apps crash on OS X 10.6.8 Status in QEMU: New Bug description: qemu-2.0.0-rc0 (and 1.7.1) crashes with SIGABORT in all apps when configured with --with-coroutine=sigaltstack (which is what configure selects by default) but all run fine if configured with --with- coroutine=gthread. Crash is at line 253 (last line of Coroutine *qemu_coroutine_new(void)) in coroutine-sigaltstack.c in 2.0.0-rc0 tarball. Platform is OS X 10.6.8 (Darwin Kernel Version 10.8.0), compiler gcc 4.2.1 Sorry for the sparse report but I'm short on time today. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1299858/+subscriptions
[Qemu-devel] [PATCH 02/18] slirp: Generalizing and neutralizing code before adding IPv6 stuff
Basically, this patch replaces arp by resolution every time arp means mac resolution and not specifically ARP. Some indentation problems are solved in functions that will be modified in the next patches (ip_input…). In if_encap, a switch is added to prepare for the IPv6 case. Some code is factorized. Some #define ETH_* are moved upper in slirp.h to make them accessible to other slirp/*.h Signed-off-by: Guillaume Subiron maet...@subiron.org Signed-off-by: Samuel Thibault samuel.thiba...@ens-lyon.org --- slirp/if.c| 2 +- slirp/mbuf.c | 2 +- slirp/mbuf.h | 2 +- slirp/slirp.c | 24 slirp/slirp.h | 12 ++-- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/slirp/if.c b/slirp/if.c index fb7acf8..e36b9cb 100644 --- a/slirp/if.c +++ b/slirp/if.c @@ -193,7 +193,7 @@ void if_start(Slirp *slirp) /* Try to send packet unless it already expired */ if (ifm-expiration_date = now !if_encap(slirp, ifm)) { -/* Packet is delayed due to pending ARP resolution */ +/* Packet is delayed due to pending ARP or NDP resolution */ continue; } diff --git a/slirp/mbuf.c b/slirp/mbuf.c index 4fefb04..92c429e 100644 --- a/slirp/mbuf.c +++ b/slirp/mbuf.c @@ -91,7 +91,7 @@ m_get(Slirp *slirp) m-m_len = 0; m-m_nextpkt = NULL; m-m_prevpkt = NULL; -m-arp_requested = false; +m-resolution_requested = false; m-expiration_date = (uint64_t)-1; end_error: DEBUG_ARG(m = %lx, (long )m); diff --git a/slirp/mbuf.h b/slirp/mbuf.h index b144f1c..38fedf4 100644 --- a/slirp/mbuf.h +++ b/slirp/mbuf.h @@ -79,7 +79,7 @@ struct mbuf { int m_len; /* Amount of data in this mbuf */ Slirp *slirp; - boolarp_requested; + boolresolution_requested; uint64_t expiration_date; /* start of dynamic buffer area, must be last element */ union { diff --git a/slirp/slirp.c b/slirp/slirp.c index bad8dad..676c86d 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -778,12 +778,14 @@ int if_encap(Slirp *slirp, struct mbuf *ifm) return 1; } +switch (iph-ip_v) { +case IPVERSION: if (!arp_table_search(slirp, iph-ip_dst.s_addr, ethaddr)) { uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)]; struct ethhdr *reh = (struct ethhdr *)arp_req; struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN); -if (!ifm-arp_requested) { +if (!ifm-resolution_requested) { /* If the client addr is not known, send an ARP request */ memset(reh-h_dest, 0xff, ETH_ALEN); memcpy(reh-h_source, special_ethaddr, ETH_ALEN - 4); @@ -809,22 +811,36 @@ int if_encap(Slirp *slirp, struct mbuf *ifm) rah-ar_tip = iph-ip_dst.s_addr; slirp-client_ipaddr = iph-ip_dst; slirp_output(slirp-opaque, arp_req, sizeof(arp_req)); -ifm-arp_requested = true; +ifm-resolution_requested = true; /* Expire request and drop outgoing packet after 1 second */ ifm-expiration_date = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + 10ULL; } return 0; } else { -memcpy(eh-h_dest, ethaddr, ETH_ALEN); memcpy(eh-h_source, special_ethaddr, ETH_ALEN - 4); /* XXX: not correct */ memcpy(eh-h_source[2], slirp-vhost_addr, 4); eh-h_proto = htons(ETH_P_IP); +break; +} + +default: +/* Do not assert while we don't manage IP6VERSION */ +/* assert(0); */ +break; +} + +memcpy(eh-h_dest, ethaddr, ETH_ALEN); +DEBUG_ARGS((dfd, src = %02x:%02x:%02x:%02x:%02x:%02x\n, +eh-h_source[0], eh-h_source[1], eh-h_source[2], +eh-h_source[3], eh-h_source[4], eh-h_source[5])); +DEBUG_ARGS((dfd, dst = %02x:%02x:%02x:%02x:%02x:%02x\n, +eh-h_dest[0], eh-h_dest[1], eh-h_dest[2], +eh-h_dest[3], eh-h_dest[4], eh-h_dest[5])); memcpy(buf + sizeof(struct ethhdr), ifm-m_data, ifm-m_len); slirp_output(slirp-opaque, buf, ifm-m_len + ETH_HLEN); return 1; -} } /* Drop host forwarding rule, return 0 if found. */ diff --git a/slirp/slirp.h b/slirp/slirp.h index e4a1bd4..cd9f2d0 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -136,6 +136,12 @@ void free(void *ptr); #include qemu/queue.h #include qemu/sockets.h +#define ETH_ALEN 6 +#define ETH_HLEN 14 + +#define ETH_P_IP 0x0800/* Internet Protocol packet */ +#define ETH_P_ARP 0x0806/* Address Resolution packet */ + #include libslirp.h #include ip.h #include tcp.h @@ -158,12 +164,6 @@ void free(void *ptr); #include bootp.h #include tftp.h -#define ETH_ALEN 6 -#define ETH_HLEN 14 - -#define ETH_P_IP 0x0800/* Internet Protocol packet */ -#define ETH_P_ARP 0x0806/* Address
[Qemu-devel] [PATCH 01/18] slirp: goto bad in udp_input if sosendto fails
Before this patch, if sosendto fails, udp_input is executed as if the packet was sent. This could cause memory leak. This patch adds a goto bad to cut the execution of this function. Signed-off-by: Guillaume Subiron maet...@subiron.org --- slirp/udp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/slirp/udp.c b/slirp/udp.c index 8cc6cb6..fd2446a 100644 --- a/slirp/udp.c +++ b/slirp/udp.c @@ -218,6 +218,7 @@ udp_input(register struct mbuf *m, int iphlen) *ip=save_ip; DEBUG_MISC((dfd,udp tx errno = %d-%s\n,errno,strerror(errno))); icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); + goto bad; } m_free(so-so_m); /* used for ICMP if error on sorecvfrom */ -- 1.9.0
[Qemu-devel] [PATCH 18/18] qapi-schema, qemu-options slirp: Adding Qemu options for IPv6 addresses
This patch adds parameters to manage some new options in the qemu -net command. Slirp IPv6 address, network prefix, and DNS IPv6 address can be given in argument to the qemu command. Defaults parameters are respectively fec0::2, fec0::, /64 and fec0::3. Signed-off-by: Yann Bordenave m...@meowstars.org Signed-off-by: Samuel Thibault samuel.thiba...@ens-lyon.org --- net/net.c| 30 ++ net/slirp.c | 46 -- qapi-schema.json | 40 ++-- qemu-options.hx | 18 -- slirp/libslirp.h | 8 +--- slirp/slirp.c| 20 +--- 6 files changed, 126 insertions(+), 36 deletions(-) diff --git a/net/net.c b/net/net.c index 2c3af20..e62e9fb 100644 --- a/net/net.c +++ b/net/net.c @@ -817,6 +817,36 @@ int net_client_init(QemuOpts *opts, int is_netdev, Error **errp) int ret = -1; { +/* Parse convenience option format ip6-net=fec0::0[/64] */ +const char *ip6_net = qemu_opt_get(opts, ip6-net); + +if (ip6_net) { +char buf[strlen(ip6_net)+1]; + +if (get_str_sep(buf, sizeof(buf), ip6_net, '/') 0) { +/* Default 64bit prefix length. */ +qemu_opt_set(opts, ip6-prefix, ip6_net); +qemu_opt_set_number(opts, ip6-prefixlen, 64); +} else { +/* User-specified prefix length. */ +int len; +char *end; + +qemu_opt_set(opts, ip6-prefix, buf); +len = strtol(ip6_net, end, 10); + +if (*end != '\0') { +error_set(errp, QERR_INVALID_PARAMETER_VALUE, + ip6-prefix, a number); +} else { +qemu_opt_set_number(opts, ip6-prefixlen, len); +} +} +qemu_opt_unset(opts, ip6-net); +} +} + +{ OptsVisitor *ov = opts_visitor_new(opts); net_visit(opts_get_visitor(ov), is_netdev, object, err); diff --git a/net/slirp.c b/net/slirp.c index 124e953..a3142f0 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -134,17 +134,23 @@ static NetClientInfo net_slirp_info = { static int net_slirp_init(NetClientState *peer, const char *model, const char *name, int restricted, const char *vnetwork, const char *vhost, + const char *vprefix6, int vprefix6_len, + const char *vhost6, const char *vhostname, const char *tftp_export, const char *bootfile, const char *vdhcp_start, - const char *vnameserver, const char *smb_export, - const char *vsmbserver, const char **dnssearch) + const char *vnameserver, const char *vnameserver6, + const char *smb_export, const char *vsmbserver, + const char **dnssearch) { /* default settings according to historic slirp */ struct in_addr net = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */ struct in_addr mask = { .s_addr = htonl(0xff00) }; /* 255.255.255.0 */ struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */ +struct in6_addr ip6_prefix; +struct in6_addr ip6_host; struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */ struct in_addr dns = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */ +struct in6_addr ip6_dns; #ifndef _WIN32 struct in_addr smbsrv = { .s_addr = 0 }; #endif @@ -212,6 +218,24 @@ static int net_slirp_init(NetClientState *peer, const char *model, return -1; } +if (!vprefix6) +vprefix6 = fec0::; +if (!inet_pton(AF_INET6, vprefix6, ip6_prefix)) { +return -1; +} + +if (!vprefix6_len) +vprefix6_len = 64; +if (vprefix6_len 0 || vprefix6_len 128) { +return -1; +} + +if (!vhost6) +vhost6 = fec0::2; +if (!inet_pton(AF_INET6, vhost6, ip6_host)) { +return -1; +} + if (vnameserver !inet_aton(vnameserver, dns)) { return -1; } @@ -220,6 +244,12 @@ static int net_slirp_init(NetClientState *peer, const char *model, return -1; } +if (!vnameserver6) +vnameserver6 = fec0::3; +if (!inet_pton(AF_INET6, vnameserver6, ip6_dns)) { +return -1; +} + if (vdhcp_start !inet_aton(vdhcp_start, dhcp)) { return -1; } @@ -242,8 +272,10 @@ static int net_slirp_init(NetClientState *peer, const char *model, s = DO_UPCAST(SlirpState, nc, nc); -s-slirp = slirp_init(restricted, net, mask, host, vhostname, - tftp_export, bootfile, dhcp, dns, dnssearch, s); +s-slirp = slirp_init(restricted, net, mask, host, + ip6_prefix, vprefix6_len, ip6_host,
[Qemu-devel] [PATCH 09/18] qemu/timer.h : Adding function to second scale
This patch adds SCALE_S, timer_new_s(), and qemu_clock_get_s in qemu/timer.h to manage second-scale timers. Signed-off-by: Guillaume Subiron maet...@subiron.org Signed-off-by: Samuel Thibault samuel.thiba...@ens-lyon.org --- include/qemu/timer.h | 32 1 file changed, 32 insertions(+) diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 7f9a074..b46601c 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -7,6 +7,7 @@ /* timers */ +#define SCALE_S 10 #define SCALE_MS 100 #define SCALE_US 1000 #define SCALE_NS 1 @@ -81,6 +82,20 @@ extern QEMUTimerListGroup main_loop_tlg; int64_t qemu_clock_get_ns(QEMUClockType type); /** + * qemu_clock_get_s; + * @type: the clock type + * + * Get the second value of a clock with + * type @type + * + * Returns: the clock value in seconds + */ +static inline int64_t qemu_clock_get_s(QEMUClockType type) +{ +return qemu_clock_get_ns(type) / SCALE_S; +} + +/** * qemu_clock_get_ms; * @type: the clock type * @@ -514,6 +529,23 @@ static inline QEMUTimer *timer_new_ms(QEMUClockType type, QEMUTimerCB *cb, } /** + * timer_new_s: + * @clock: the clock to associate with the timer + * @callback: the callback to call when the timer expires + * @opaque: the opaque pointer to pass to the callback + * + * Create a new timer with second scale on the default timer list + * associated with the clock. + * + * Returns: a pointer to the newly created timer + */ +static inline QEMUTimer *timer_new_s(QEMUClockType type, QEMUTimerCB *cb, + void *opaque) +{ +return timer_new(type, SCALE_S, cb, opaque); +} + +/** * timer_free: * @ts: the timer * -- 1.9.0
[Qemu-devel] [PATCH 05/18] slirp: Factorizing address translation
This patch factorizes some duplicate code into a new function, sotranslate_out(). This function perform the address translation when a packet is transmitted to the host network. If the paquet is destinated to the host, the loopback address is used, and if the paquet is destinated to the virtual DNS, the real DNS address is used. This code is just a copy of the existant, but factorized and ready to manage the IPv6 case. On the same model, the major part of udp_output() code is moved into a new sotranslate_in(). This function is directly used in sorecvfrom(), like sotranslate_out() in sosendto(). udp_output() becoming useless, it is removed and udp_output2() is renamed into udp_output(). This adds consistency with the udp6_output() function introduced by further patches. Signed-off-by: Guillaume Subiron maet...@subiron.org --- slirp/bootp.c| 2 +- slirp/ip_icmp.c | 19 +++- slirp/socket.c | 93 slirp/socket.h | 3 ++ slirp/tcp_subr.c | 24 +++ slirp/tftp.c | 6 ++-- slirp/udp.c | 27 +--- slirp/udp.h | 3 +- 8 files changed, 91 insertions(+), 86 deletions(-) diff --git a/slirp/bootp.c b/slirp/bootp.c index b7db9fa..03e2e42 100644 --- a/slirp/bootp.c +++ b/slirp/bootp.c @@ -319,7 +319,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) m-m_len = sizeof(struct bootp_t) - sizeof(struct ip) - sizeof(struct udphdr); -udp_output2(NULL, m, saddr, daddr, IPTOS_LOWDELAY); +udp_output(NULL, m, saddr, daddr, IPTOS_LOWDELAY); } void bootp_input(struct mbuf *m) diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c index 7c364da..663885f 100644 --- a/slirp/ip_icmp.c +++ b/slirp/ip_icmp.c @@ -157,7 +157,7 @@ icmp_input(struct mbuf *m, int hlen) goto freeit; } else { struct socket *so; - struct sockaddr_in addr; + struct sockaddr_storage addr; if ((so = socreate(slirp)) == NULL) goto freeit; if (icmp_send(so, m, hlen) == 0) { return; @@ -181,20 +181,9 @@ icmp_input(struct mbuf *m, int hlen) so-so_state = SS_ISFCONNECTED; /* Send the packet */ - addr.sin_family = AF_INET; - if ((so-so_faddr.s_addr slirp-vnetwork_mask.s_addr) == - slirp-vnetwork_addr.s_addr) { - /* It's an alias */ - if (so-so_faddr.s_addr == slirp-vnameserver_addr.s_addr) { - if (get_dns_addr(addr.sin_addr) 0) - addr.sin_addr = loopback_addr; - } else { - addr.sin_addr = loopback_addr; - } - } else { - addr.sin_addr = so-so_faddr; - } - addr.sin_port = so-so_fport; + addr = so-fhost.ss; + sotranslate_out(so, addr); + if(sendto(so-s, icmp_ping_msg, strlen(icmp_ping_msg), 0, (struct sockaddr *)addr, sizeof(addr)) == -1) { DEBUG_MISC((dfd,icmp_input udp sendto tx errno = %d-%s\n, diff --git a/slirp/socket.c b/slirp/socket.c index e6723bc..c0c8bc1 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -438,6 +438,7 @@ void sorecvfrom(struct socket *so) { struct sockaddr_storage addr; + struct sockaddr_storage saddr, daddr; socklen_t addrlen = sizeof(struct sockaddr_storage); DEBUG_CALL(sorecvfrom); @@ -525,11 +526,17 @@ sorecvfrom(struct socket *so) /* * If this packet was destined for CTL_ADDR, -* make it look like that's where it came from, done by udp_output +* make it look like that's where it came from */ + saddr = addr; + sotranslate_in(so, saddr); + daddr = so-lhost.ss; + switch (so-so_ffamily) { case AF_INET: - udp_output(so, m, (struct sockaddr_in *) addr); + udp_output(so, m, (struct sockaddr_in *) saddr, + (struct sockaddr_in *) daddr, + so-so_iptos); break; default: break; @@ -544,33 +551,20 @@ sorecvfrom(struct socket *so) int sosendto(struct socket *so, struct mbuf *m) { - Slirp *slirp = so-slirp; int ret; - struct sockaddr_in addr; + struct sockaddr_storage addr; DEBUG_CALL(sosendto); DEBUG_ARG(so = %lx, (long)so); DEBUG_ARG(m = %lx, (long)m); -addr.sin_family = AF_INET; - if ((so-so_faddr.s_addr slirp-vnetwork_mask.s_addr) == - slirp-vnetwork_addr.s_addr) { - /* It's an alias */ - if (so-so_faddr.s_addr == slirp-vnameserver_addr.s_addr) { - if (get_dns_addr(addr.sin_addr) 0) - addr.sin_addr = loopback_addr; - } else { - addr.sin_addr = loopback_addr; - } - } else - addr.sin_addr = so-so_faddr; - addr.sin_port = so-so_fport; - - DEBUG_MISC((dfd, sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n, ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
[Qemu-devel] [PATCH 04/18] slirp: Make Socket structure IPv6 compatible
This patch replaces foreign and local address/port couples in Socket structure by 2 sockaddr_storage which can be casted in sockaddr_in or sockaddr_in6. Direct access to address and port is still possible thanks to some \#define, so retrocompatibility of the existing code is assured. The ss_family field of sockaddr_storage is declared after each socket creation. The whole structure is also saved/restored when a Qemu session is saved/restored. Signed-off-by: Guillaume Subiron maet...@subiron.org --- slirp/ip_icmp.c | 2 ++ slirp/slirp.c | 48 slirp/socket.c| 14 +++--- slirp/socket.h| 25 + slirp/tcp_input.c | 2 ++ slirp/tcp_subr.c | 2 ++ slirp/udp.c | 4 7 files changed, 82 insertions(+), 15 deletions(-) diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c index 9f1cb08..7c364da 100644 --- a/slirp/ip_icmp.c +++ b/slirp/ip_icmp.c @@ -170,8 +170,10 @@ icmp_input(struct mbuf *m, int hlen) goto end_error; } so-so_m = m; + so-so_ffamily = AF_INET; so-so_faddr = ip-ip_dst; so-so_fport = htons(7); + so-so_lfamily = AF_INET; so-so_laddr = ip-ip_src; so-so_lport = htons(9); so-so_iptos = ip-ip_tos; diff --git a/slirp/slirp.c b/slirp/slirp.c index bfc4832..53af9e7 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -1025,10 +1025,26 @@ static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf) static void slirp_socket_save(QEMUFile *f, struct socket *so) { qemu_put_be32(f, so-so_urgc); -qemu_put_be32(f, so-so_faddr.s_addr); -qemu_put_be32(f, so-so_laddr.s_addr); -qemu_put_be16(f, so-so_fport); -qemu_put_be16(f, so-so_lport); +qemu_put_be16(f, so-so_ffamily); +switch (so-so_ffamily) { +case AF_INET: +qemu_put_be32(f, so-so_faddr.s_addr); +qemu_put_be16(f, so-so_fport); +break; +default: +fprintf(stderr, +so_ffamily unknown, unable to save so_faddr and so_fport\n); +} +qemu_put_be16(f, so-so_lfamily); +switch (so-so_lfamily) { +case AF_INET: +qemu_put_be32(f, so-so_laddr.s_addr); +qemu_put_be16(f, so-so_lport); +break; +default: +fprintf(stderr, +so_ffamily unknown, unable to save so_laddr and so_lport\n); +} qemu_put_byte(f, so-so_iptos); qemu_put_byte(f, so-so_emu); qemu_put_byte(f, so-so_type); @@ -1148,10 +1164,26 @@ static int slirp_socket_load(QEMUFile *f, struct socket *so) return -ENOMEM; so-so_urgc = qemu_get_be32(f); -so-so_faddr.s_addr = qemu_get_be32(f); -so-so_laddr.s_addr = qemu_get_be32(f); -so-so_fport = qemu_get_be16(f); -so-so_lport = qemu_get_be16(f); +so-so_ffamily = qemu_get_be16(f); +switch (so-so_ffamily) { +case AF_INET: +so-so_faddr.s_addr = qemu_get_be32(f); +so-so_fport = qemu_get_be16(f); +break; +default: +fprintf(stderr, +so_ffamily unknown, unable to restore so_faddr and so_lport\n); +} +so-so_lfamily = qemu_get_be16(f); +switch (so-so_lfamily) { +case AF_INET: +so-so_laddr.s_addr = qemu_get_be32(f); +so-so_lport = qemu_get_be16(f); +break; +default: +fprintf(stderr, +so_ffamily unknown, unable to restore so_laddr and so_lport\n); +} so-so_iptos = qemu_get_byte(f); so-so_emu = qemu_get_byte(f); so-so_type = qemu_get_byte(f); diff --git a/slirp/socket.c b/slirp/socket.c index 37ac5cf..e6723bc 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -437,8 +437,8 @@ sowrite(struct socket *so) void sorecvfrom(struct socket *so) { - struct sockaddr_in addr; - socklen_t addrlen = sizeof(struct sockaddr_in); + struct sockaddr_storage addr; + socklen_t addrlen = sizeof(struct sockaddr_storage); DEBUG_CALL(sorecvfrom); DEBUG_ARG(so = %lx, (long)so); @@ -527,7 +527,13 @@ sorecvfrom(struct socket *so) * If this packet was destined for CTL_ADDR, * make it look like that's where it came from, done by udp_output */ - udp_output(so, m, addr); + switch (so-so_ffamily) { + case AF_INET: + udp_output(so, m, (struct sockaddr_in *) addr); + break; + default: + break; + } } /* rx error */ } /* if ping packet */ } @@ -619,6 +625,7 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, so-so_state = SS_PERSISTENT_MASK; so-so_state |= (SS_FACCEPTCONN | flags); + so-so_lfamily = AF_INET; so-so_lport = lport; /* Kept in network format */ so-so_laddr.s_addr = laddr; /* Ditto */ @@ -645,6 +652,7 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, opt, sizeof(int));
[Qemu-devel] [PATCH 03/18] slirp: Reindent after refactoring
No code change. Signed-off-by: Guillaume Subiron maet...@subiron.org Signed-off-by: Samuel Thibault samuel.thiba...@ens-lyon.org --- slirp/slirp.c | 107 +- 1 file changed, 54 insertions(+), 53 deletions(-) diff --git a/slirp/slirp.c b/slirp/slirp.c index 676c86d..bfc4832 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -780,50 +780,51 @@ int if_encap(Slirp *slirp, struct mbuf *ifm) switch (iph-ip_v) { case IPVERSION: -if (!arp_table_search(slirp, iph-ip_dst.s_addr, ethaddr)) { -uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)]; -struct ethhdr *reh = (struct ethhdr *)arp_req; -struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN); - -if (!ifm-resolution_requested) { -/* If the client addr is not known, send an ARP request */ -memset(reh-h_dest, 0xff, ETH_ALEN); -memcpy(reh-h_source, special_ethaddr, ETH_ALEN - 4); -memcpy(reh-h_source[2], slirp-vhost_addr, 4); -reh-h_proto = htons(ETH_P_ARP); -rah-ar_hrd = htons(1); -rah-ar_pro = htons(ETH_P_IP); -rah-ar_hln = ETH_ALEN; -rah-ar_pln = 4; -rah-ar_op = htons(ARPOP_REQUEST); - -/* source hw addr */ -memcpy(rah-ar_sha, special_ethaddr, ETH_ALEN - 4); -memcpy(rah-ar_sha[2], slirp-vhost_addr, 4); - -/* source IP */ -rah-ar_sip = slirp-vhost_addr.s_addr; - -/* target hw addr (none) */ -memset(rah-ar_tha, 0, ETH_ALEN); - -/* target IP */ -rah-ar_tip = iph-ip_dst.s_addr; -slirp-client_ipaddr = iph-ip_dst; -slirp_output(slirp-opaque, arp_req, sizeof(arp_req)); -ifm-resolution_requested = true; - -/* Expire request and drop outgoing packet after 1 second */ -ifm-expiration_date = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + 10ULL; +if (!arp_table_search(slirp, iph-ip_dst.s_addr, ethaddr)) { +uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)]; +struct ethhdr *reh = (struct ethhdr *)arp_req; +struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN); + +if (!ifm-resolution_requested) { +/* If the client addr is not known, send an ARP request */ +memset(reh-h_dest, 0xff, ETH_ALEN); +memcpy(reh-h_source, special_ethaddr, ETH_ALEN - 4); +memcpy(reh-h_source[2], slirp-vhost_addr, 4); +reh-h_proto = htons(ETH_P_ARP); +rah-ar_hrd = htons(1); +rah-ar_pro = htons(ETH_P_IP); +rah-ar_hln = ETH_ALEN; +rah-ar_pln = 4; +rah-ar_op = htons(ARPOP_REQUEST); + +/* source hw addr */ +memcpy(rah-ar_sha, special_ethaddr, ETH_ALEN - 4); +memcpy(rah-ar_sha[2], slirp-vhost_addr, 4); + +/* source IP */ +rah-ar_sip = slirp-vhost_addr.s_addr; + +/* target hw addr (none) */ +memset(rah-ar_tha, 0, ETH_ALEN); + +/* target IP */ +rah-ar_tip = iph-ip_dst.s_addr; +slirp-client_ipaddr = iph-ip_dst; +slirp_output(slirp-opaque, arp_req, sizeof(arp_req)); +ifm-resolution_requested = true; + +/* Expire request and drop outgoing packet after 1 second */ +ifm-expiration_date = +qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + 10ULL; +} +return 0; +} else { +memcpy(eh-h_source, special_ethaddr, ETH_ALEN - 4); +/* XXX: not correct */ +memcpy(eh-h_source[2], slirp-vhost_addr, 4); +eh-h_proto = htons(ETH_P_IP); +break; } -return 0; -} else { -memcpy(eh-h_source, special_ethaddr, ETH_ALEN - 4); -/* XXX: not correct */ -memcpy(eh-h_source[2], slirp-vhost_addr, 4); -eh-h_proto = htons(ETH_P_IP); -break; -} default: /* Do not assert while we don't manage IP6VERSION */ @@ -831,16 +832,16 @@ int if_encap(Slirp *slirp, struct mbuf *ifm) break; } -memcpy(eh-h_dest, ethaddr, ETH_ALEN); -DEBUG_ARGS((dfd, src = %02x:%02x:%02x:%02x:%02x:%02x\n, -eh-h_source[0], eh-h_source[1], eh-h_source[2], -eh-h_source[3], eh-h_source[4], eh-h_source[5])); -DEBUG_ARGS((dfd, dst = %02x:%02x:%02x:%02x:%02x:%02x\n, -eh-h_dest[0], eh-h_dest[1], eh-h_dest[2], -eh-h_dest[3], eh-h_dest[4], eh-h_dest[5])); -memcpy(buf + sizeof(struct ethhdr), ifm-m_data, ifm-m_len); -slirp_output(slirp-opaque, buf, ifm-m_len + ETH_HLEN); -return 1; +memcpy(eh-h_dest, ethaddr, ETH_ALEN); +
[Qemu-devel] [PATCH 16/18] slirp: Handle IPv6 in TCP functions
This patch adds IPv6 case in TCP functions refactored by the last patches. This also adds IPv6 pseudo-header in tcpiphdr structure. Finally, tcp_input() is called by ip6_input(). Signed-off-by: Guillaume Subiron maet...@subiron.org Signed-off-by: Samuel Thibault samuel.thiba...@ens-lyon.org --- slirp/ip6_input.c | 4 ++-- slirp/tcp.h| 2 ++ slirp/tcp_input.c | 58 +- slirp/tcp_output.c | 16 +++ slirp/tcp_subr.c | 36 + slirp/tcpip.h | 9 + 6 files changed, 105 insertions(+), 20 deletions(-) diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c index 3290af8..b03b795 100644 --- a/slirp/ip6_input.c +++ b/slirp/ip6_input.c @@ -58,8 +58,8 @@ void ip6_input(struct mbuf *m) */ switch (ip6-ip_nh) { case IPPROTO_TCP: -/* :TODO:maethor:130307: TCP */ -icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE); +NTOHS(ip6-ip_pl); +tcp_input(m, sizeof(struct ip6), (struct socket *)NULL, AF_INET6); break; case IPPROTO_UDP: udp6_input(m); diff --git a/slirp/tcp.h b/slirp/tcp.h index 2e2b403..61befcd 100644 --- a/slirp/tcp.h +++ b/slirp/tcp.h @@ -106,6 +106,8 @@ struct tcphdr { */ #undef TCP_MSS #defineTCP_MSS 1460 +#undef TCP6_MSS +#define TCP6_MSS 1440 #undef TCP_MAXWIN #defineTCP_MAXWIN 65535 /* largest value for (unscaled) window */ diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c index 3409557..e5056f8 100644 --- a/slirp/tcp_input.c +++ b/slirp/tcp_input.c @@ -215,7 +215,8 @@ present: void tcp_input(struct mbuf *m, int iphlen, struct socket *inso, sa_family_t af) { - struct ip save_ip, *ip; + struct ip save_ip, *ip; + struct ip6 save_ip6, *ip6; register struct tcpiphdr *ti; caddr_t optp = NULL; int optlen = 0; @@ -254,6 +255,11 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, sa_family_t af) } slirp = m-slirp; + ip = mtod(m, struct ip *); + ip6 = mtod(m, struct ip6 *); + save_ip = *ip; + save_ip6 = *ip6; + switch (af) { case AF_INET: if (iphlen sizeof(struct ip)) { @@ -262,13 +268,6 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, sa_family_t af) } /* XXX Check if too short */ - - /* -* Save a copy of the IP header in case we want restore it -* for sending an ICMP error message in response. -*/ - ip = mtod(m, struct ip *); - save_ip = *ip; save_ip.ip_len += iphlen; /* @@ -293,16 +292,35 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, sa_family_t af) ti-ti_dst = save_ip.ip_dst; ti-ti_pr = save_ip.ip_p; ti-ti_len = htons((uint16_t)tlen); - len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen); - if (cksum(m, len)) { - goto drop; - } + break; + + case AF_INET6: + m-m_data -= sizeof(struct tcpiphdr) - (sizeof(struct ip6) ++ sizeof(struct tcphdr)); + m-m_len += sizeof(struct tcpiphdr) - (sizeof(struct ip6) ++ sizeof(struct tcphdr)); + ti = mtod(m, struct tcpiphdr *); + + tlen = ip6-ip_pl; + tcpiphdr2qlink(ti)-next = tcpiphdr2qlink(ti)-prev = NULL; + memset(ti-ih_mbuf, 0 , sizeof(struct mbuf_ptr)); + memset(ti-ti, 0, sizeof(ti-ti)); + ti-ti_x0 = 0; + ti-ti_src6 = save_ip6.ip_src; + ti-ti_dst6 = save_ip6.ip_dst; + ti-ti_nh6 = save_ip6.ip_nh; + ti-ti_len = htons((uint16_t)tlen); break; default: goto drop; } + len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen); + if (cksum(m, len)) { + goto drop; + } + /* * Check that TCP offset makes sense, * pull out TCP options and adjust length. XXX @@ -346,6 +364,12 @@ findso: ((struct sockaddr_in *)fhost)-sin_addr = ti-ti_dst; ((struct sockaddr_in *)fhost)-sin_port = ti-ti_dport; break; + case AF_INET6: + ((struct sockaddr_in6 *)lhost)-sin6_addr = ti-ti_src6; + ((struct sockaddr_in6 *)lhost)-sin6_port = ti-ti_sport; + ((struct sockaddr_in6 *)fhost)-sin6_addr = ti-ti_dst6; + ((struct sockaddr_in6 *)fhost)-sin6_port = ti-ti_dport; + break; default: goto drop; } @@ -405,7 +429,6 @@ findso: so-so_iptos = ((struct ip *)ti)-ip_tos; break; default: - goto drop; break; } } @@ -634,6 +657,9 @@ findso: case AF_INET:
[Qemu-devel] [PATCH 14/18] slirp: Generalizing and neutralizing various TCP functions before adding IPv6 stuff
Basically, this patch adds some switch in various TCP functions to prepare them for the IPv6 case. To have something to switch in tcp_input() and tcp_respond(), a new argument is used to give them the sa_family of the addresses they are working on. Signed-off-by: Guillaume Subiron maet...@subiron.org --- slirp/ip_input.c | 2 +- slirp/slirp.c | 6 -- slirp/slirp.h | 4 ++-- slirp/tcp_input.c | 53 + slirp/tcp_output.c | 14 +++--- slirp/tcp_subr.c | 48 +--- slirp/tcp_timer.c | 3 ++- 7 files changed, 98 insertions(+), 32 deletions(-) diff --git a/slirp/ip_input.c b/slirp/ip_input.c index 1925cdc..9aa8909 100644 --- a/slirp/ip_input.c +++ b/slirp/ip_input.c @@ -199,7 +199,7 @@ ip_input(struct mbuf *m) */ switch (ip-ip_p) { case IPPROTO_TCP: - tcp_input(m, hlen, (struct socket *)NULL); + tcp_input(m, hlen, (struct socket *)NULL, AF_INET); break; case IPPROTO_UDP: udp_input(m, hlen); diff --git a/slirp/slirp.c b/slirp/slirp.c index 33ed0cd..7f2ed70 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -576,7 +576,8 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error) /* * Continue tcp_input */ -tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); +tcp_input((struct mbuf *)NULL, sizeof(struct ip), so, +so-so_ffamily); /* continue; */ } else { ret = sowrite(so); @@ -625,7 +626,8 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error) } } -tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); +tcp_input((struct mbuf *)NULL, sizeof(struct ip), so, +so-so_ffamily); } /* SS_ISFCONNECTING */ #endif } diff --git a/slirp/slirp.h b/slirp/slirp.h index d16400b..6c06505 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -354,7 +354,7 @@ void ip6_input(struct mbuf *); int ip6_output(struct socket *, struct mbuf *, int fast); /* tcp_input.c */ -void tcp_input(register struct mbuf *, int, struct socket *); +void tcp_input(register struct mbuf *, int, struct socket *, sa_family_t af); int tcp_mss(register struct tcpcb *, u_int); /* tcp_output.c */ @@ -365,7 +365,7 @@ void tcp_setpersist(register struct tcpcb *); void tcp_init(Slirp *); void tcp_cleanup(Slirp *); void tcp_template(struct tcpcb *); -void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int); +void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int, sa_family_t); struct tcpcb * tcp_newtcpcb(struct socket *); struct tcpcb * tcp_close(register struct tcpcb *); void tcp_sockclosed(struct tcpcb *); diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c index dde89b6..48b7fc6 100644 --- a/slirp/tcp_input.c +++ b/slirp/tcp_input.c @@ -213,7 +213,7 @@ present: * protocol specification dated September, 1981 very closely. */ void -tcp_input(struct mbuf *m, int iphlen, struct socket *inso) +tcp_input(struct mbuf *m, int iphlen, struct socket *inso, sa_family_t af) { struct ip save_ip, *ip; register struct tcpiphdr *ti; @@ -254,6 +254,8 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso) } slirp = m-slirp; + switch (af) { + case AF_INET: if (iphlen sizeof(struct ip )) { ip_stripoptions(m, (struct mbuf *)0); iphlen=sizeof(struct ip ); @@ -295,6 +297,11 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso) if(cksum(m, len)) { goto drop; } + break; + + default: + goto drop; + } /* * Check that TCP offset makes sense, @@ -330,12 +337,18 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso) * Locate pcb for segment. */ findso: - lhost.ss_family = AF_INET; + lhost.ss_family = af; + fhost.ss_family = af; + switch (af) { + case AF_INET: ((struct sockaddr_in *)lhost)-sin_addr = ti-ti_src; ((struct sockaddr_in *)lhost)-sin_port = ti-ti_sport; - fhost.ss_family = AF_INET; ((struct sockaddr_in *)fhost)-sin_addr = ti-ti_dst; ((struct sockaddr_in *)fhost)-sin_port = ti-ti_dport; + break; + default: + goto drop; + } so = solookup(slirp-tcp_last_so, slirp-tcb, lhost, fhost); @@ -385,8 +398,17 @@ findso: so-lhost.ss = lhost; so-fhost.ss = fhost; - if ((so-so_iptos = tcp_tos(so)) == 0) + so-so_iptos = tcp_tos(so); + if
[Qemu-devel] [PATCH 07/18] slirp: Make udp_attach IPv6 compatible
A sa_family_t is now passed in argument to udp_attach instead of using a hardcoded AF_INET to call qemu_socket(). Signed-off-by: Guillaume Subiron maet...@subiron.org --- slirp/ip_icmp.c | 2 +- slirp/udp.c | 7 --- slirp/udp.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c index 663885f..382b5dd 100644 --- a/slirp/ip_icmp.c +++ b/slirp/ip_icmp.c @@ -162,7 +162,7 @@ icmp_input(struct mbuf *m, int hlen) if (icmp_send(so, m, hlen) == 0) { return; } - if(udp_attach(so) == -1) { + if (udp_attach(so, AF_INET) == -1) { DEBUG_MISC((dfd,icmp_input udp_attach errno = %d-%s\n, errno,strerror(errno))); sofree(so); diff --git a/slirp/udp.c b/slirp/udp.c index 94f104d..d5be05f 100644 --- a/slirp/udp.c +++ b/slirp/udp.c @@ -167,7 +167,7 @@ udp_input(register struct mbuf *m, int iphlen) if (!so) { goto bad; } - if(udp_attach(so) == -1) { + if (udp_attach(so, AF_INET) == -1) { DEBUG_MISC((dfd, udp_attach errno = %d-%s\n, errno,strerror(errno))); sofree(so); @@ -275,9 +275,10 @@ int udp_output(struct socket *so, struct mbuf *m, } int -udp_attach(struct socket *so) +udp_attach(struct socket *so, sa_family_t af) { - if((so-s = qemu_socket(AF_INET,SOCK_DGRAM,0)) != -1) { + so-s = qemu_socket(af, SOCK_DGRAM, 0); + if (so-s != -1) { so-so_expire = curtime + SO_EXPIRE; insque(so, so-slirp-udb); } diff --git a/slirp/udp.h b/slirp/udp.h index a04b8ce..15e73c1 100644 --- a/slirp/udp.h +++ b/slirp/udp.h @@ -76,7 +76,7 @@ struct mbuf; void udp_init(Slirp *); void udp_cleanup(Slirp *); void udp_input(register struct mbuf *, int); -int udp_attach(struct socket *); +int udp_attach(struct socket *, sa_family_t af); void udp_detach(struct socket *); struct socket * udp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int, int); -- 1.9.0
[Qemu-devel] [PATCH 12/18] slirp: Adding IPv6 UDP support
This patch adds udp6_input() and udp6_output(). It also adds the IPv6 case in sorecvfrom(). Finally, udp_input() is called by ip6_input(). Signed-off-by: Guillaume Subiron maet...@subiron.org --- slirp/Makefile.objs | 2 +- slirp/ip6_input.c | 3 +- slirp/socket.c | 7 ++- slirp/udp.h | 5 ++ slirp/udp6.c| 149 5 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 slirp/udp6.c diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs index 2dfe8e0..faa32b6 100644 --- a/slirp/Makefile.objs +++ b/slirp/Makefile.objs @@ -1,3 +1,3 @@ common-obj-y = cksum.o if.o ip_icmp.o ip6_icmp.o ip6_input.o ip6_output.o ip_input.o ip_output.o dnssearch.o common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o -common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o ndp_table.o +common-obj-y += tcp_subr.o tcp_timer.o udp.o udp6.o bootp.o tftp.o arp_table.o ndp_table.o diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c index af098a5..3290af8 100644 --- a/slirp/ip6_input.c +++ b/slirp/ip6_input.c @@ -62,8 +62,7 @@ void ip6_input(struct mbuf *m) icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE); break; case IPPROTO_UDP: -/* :TODO:maethor:130312: UDP */ -icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE); +udp6_input(m); break; case IPPROTO_ICMPV6: icmp6_input(m); diff --git a/slirp/socket.c b/slirp/socket.c index f333fcf..31bbb7e 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -540,8 +540,13 @@ sorecvfrom(struct socket *so) (struct sockaddr_in *) daddr, so-so_iptos); break; - default: + case AF_INET6: + udp6_output(so, m, (struct sockaddr_in6 *) saddr, + (struct sockaddr_in6 *) daddr); break; + default: + assert(0); + break; } } /* rx error */ } /* if ping packet */ diff --git a/slirp/udp.h b/slirp/udp.h index 15e73c1..8a4d9f5 100644 --- a/slirp/udp.h +++ b/slirp/udp.h @@ -83,4 +83,9 @@ struct socket * udp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int, int udp_output(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, struct sockaddr_in *daddr, int iptos); + +void udp6_input(register struct mbuf *); +int udp6_output(struct socket *so, struct mbuf *m, +struct sockaddr_in6 *saddr, struct sockaddr_in6 *daddr); + #endif diff --git a/slirp/udp6.c b/slirp/udp6.c new file mode 100644 index 000..3940959 --- /dev/null +++ b/slirp/udp6.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2013 + * Guillaume Subiron + * + * Please read the file COPYRIGHT for the + * terms and conditions of the copyright. + */ + +#include slirp.h +#include udp.h + +void udp6_input(struct mbuf *m) +{ +Slirp *slirp = m-slirp; +struct ip6 *ip, save_ip; +struct udphdr *uh; +int hlen = sizeof(struct ip6); +int len; +struct socket *so; +struct sockaddr_storage lhost; + +DEBUG_CALL(udp6_input); +DEBUG_ARG(m = %lx, (long)m); + +if (slirp-restricted) { +goto bad; +} + +ip = mtod(m, struct ip6 *); +m-m_len -= hlen; +m-m_data += hlen; +uh = mtod(m, struct udphdr *); +m-m_len += hlen; +m-m_data -= hlen; + +if (ip6_cksum(m)) { +goto bad; +} + +len = ntohs((uint16_t)uh-uh_ulen); + +/* + * Make mbuf data length reflect UDP length. + * If not enough data to reflect UDP length, drop. + */ +if (ntohs(ip-ip_pl) != len) { +if (len ntohs(ip-ip_pl)) { +goto bad; +} +m_adj(m, len - ntohs(ip-ip_pl)); +ip-ip_pl = htons(len); +} + +/* TODO handle DHCP/BOOTP */ +/* TODO handle TFTP */ + +/* Locate pcb for datagram. */ +lhost.ss_family = AF_INET6; +((struct sockaddr_in6 *)lhost)-sin6_addr = ip-ip_src; +((struct sockaddr_in6 *)lhost)-sin6_port = uh-uh_sport; + +so = solookup(slirp-udp_last_so, slirp-udb, lhost, NULL); + +if (so == NULL) { +/* If there's no socket for this packet, create one. */ +so = socreate(slirp); +if (!so) { +goto bad; +} +if (udp_attach(so, AF_INET6) == -1) { +DEBUG_MISC((dfd, udp6_attach errno = %d-%s\n, +errno, strerror(errno))); +sofree(so); +goto bad; +} + +/* Setup fields */ +so-so_lfamily = AF_INET6; +so-so_laddr6 = ip-ip_src; +so-so_lport6 = uh-uh_sport; +} + +so-so_ffamily = AF_INET6; +so-so_faddr6 = ip-ip_dst; /* XXX */ +so-so_fport6 = uh-uh_dport; /* XXX */ + +hlen += sizeof(struct udphdr); +m-m_len -= hlen; +m-m_data += hlen; + +/* + * Now we sendto() the packet. + */ +
Re: [Qemu-devel] 2.0 regression: loadvm assertion with ehci + tablet
Hi, Am 30.03.2014 22:27, schrieb Cole Robinson: With git master, loadvm hits an assert failure if using ehci and usb tablet. Steps to reproduce: $ qemu-img create -f qcow2 foo.qcow2 10G $ ./x86_64-softmmu/qemu-system-x86_64 \ -enable-kvm -m 4096 \ -device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x5.0x7 \ -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x5 \ -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x5.0x1 \ -device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x5.0x2 \ -device usb-tablet,id=input0 \ -hda foo.qcow2 \ -cdrom Fedora-20-x86_64-Live-Desktop.iso \ -boot d -monitor stdio wait until guest boot to 'welcome to fedora' window (qemu) savevm foo (qemu) loadvm foo qemu-system-x86_64: hw/pci/pci.c:250: pcibus_reset: Assertion `bus-irq_count[i] == 0' failed. The relevant backtrace bits for the assertion: #4 0x7f8f7241971e in pcibus_reset (qbus=0x7f8f74082fd0) at hw/pci/pci.c:250 #5 0x7f8f723bd36d in qbus_reset_one (bus=0x7f8f74082fd0, opaque=optimized out) at hw/core/qdev.c:249 #6 0x7f8f723bec88 in qdev_walk_children (dev=0x7f8f73efb320, pre_devfn=0x0, pre_busfn=0x0, post_devfn=0x7f8f723bf4f0 qdev_reset_one, post_busfn=0x7f8f723bd320 qbus_reset_one, opaque=0x0) at hw/core/qdev.c:403 #7 0x7f8f723bedb8 in qbus_walk_children (bus=0x7f8f740706e0, pre_devfn=0x0, pre_busfn=0x0, post_devfn=0x7f8f723bf4f0 qdev_reset_one, post_busfn=0x7f8f723bd320 qbus_reset_one, opaque=0x0) at hw/core/qdev.c:369 #8 0x7f8f724f5c5d in qemu_devices_reset () at vl.c:1867 #9 qemu_system_reset (report=report@entry=false) at vl.c:1880 #10 0x7f8f7256dba2 in load_vmstate (name=name@entry=0x7f8f7417a160 foo) at /home/crobinso/src/qemu/savevm.c:1098 The 'cause' is this: #0 ehci_detach (port=0x56436968) at hw/usb/hcd-ehci.c:810 #1 0x55727b5e in usb_detach (port=port@entry=0x56436968) at hw/usb/core.c:49 #2 0x55736bf3 in ehci_reset (opaque=0x564364d8) at hw/usb/hcd-ehci.c:941 #3 0x557e1fcd in qemu_devices_reset () at vl.c:1867 #4 qemu_system_reset (report=report@entry=false) at vl.c:1880 #5 0x55859f12 in load_vmstate (name=name@entry=0x56458210 foo) at /home/crobinso/src/qemu/savevm.c:1098 ehci_reset calls usb_detach which sets pcibus-irq_count[3] = 1. pcibus_reset runs and hits the assertion. But I don't understand this stuff enough to determine what's actually wrong here :) I bisected the issue to: commit 31b030d4abc5bea89c2b33b39d3b302836f6b6ee Author: Andreas Färber afaer...@suse.de Date: Wed Sep 4 01:29:02 2013 +0200 cputlb: Change tlb_flush_page() argument to CPUState Signed-off-by: Andreas Färber afaer...@suse.de ...and then I double checked it since that sounds unrelated. Same result. You are running into an unrelated migration bug: http://git.qemu.org/?p=qemu.git;a=commit;h=c01a71c1a56fa27f43449ff59e5d03b2483658a2 Sorry about that. You'll need to patch -p1 the above commit on top of each git-bisect commit to find the actual breakage if the above commit is already bad (can't test right now). Cheers, Andreas -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
[Qemu-devel] [PATCH 08/18] slirp: Adding family argument to tcp_fconnect()
This patch simply adds a sa_family_t argument to remove the hardcoded AF_INET in the call of qemu_socket(). Signed-off-by: Guillaume Subiron maet...@subiron.org --- slirp/slirp.h | 2 +- slirp/tcp_input.c | 3 ++- slirp/tcp_subr.c | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/slirp/slirp.h b/slirp/slirp.h index cd9f2d0..4b66739 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -334,7 +334,7 @@ void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbu struct tcpcb * tcp_newtcpcb(struct socket *); struct tcpcb * tcp_close(register struct tcpcb *); void tcp_sockclosed(struct tcpcb *); -int tcp_fconnect(struct socket *); +int tcp_fconnect(struct socket *, sa_family_t af); void tcp_connect(struct socket *); int tcp_attach(struct socket *); uint8_t tcp_tos(struct socket *); diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c index 1b9a0b1..4c72430 100644 --- a/slirp/tcp_input.c +++ b/slirp/tcp_input.c @@ -581,7 +581,8 @@ findso: goto cont_input; } - if((tcp_fconnect(so) == -1) (errno != EINPROGRESS) (errno != EWOULDBLOCK)) { + if ((tcp_fconnect(so, so-so_ffamily) == -1) + (errno != EINPROGRESS) (errno != EWOULDBLOCK)) { u_char code=ICMP_UNREACH_NET; DEBUG_MISC((dfd, tcp fconnect errno = %d-%s\n, errno,strerror(errno))); diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index 4791c0c..3558115 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -324,14 +324,15 @@ tcp_sockclosed(struct tcpcb *tp) * nonblocking. Connect returns after the SYN is sent, and does * not wait for ACK+SYN. */ -int tcp_fconnect(struct socket *so) +int tcp_fconnect(struct socket *so, sa_family_t af) { int ret=0; DEBUG_CALL(tcp_fconnect); DEBUG_ARG(so = %lx, (long )so); - if( (ret = so-s = qemu_socket(AF_INET,SOCK_STREAM,0)) = 0) { + ret = so-s = qemu_socket(af, SOCK_STREAM, 0); + if (ret = 0) { int opt, s=so-s; struct sockaddr_storage addr; -- 1.9.0
[Qemu-devel] [PATCH 15/18] slirp: Reindent after refactoring
No code change. Signed-off-by: Guillaume Subiron maet...@subiron.org Signed-off-by: Samuel Thibault samuel.thiba...@ens-lyon.org --- slirp/slirp.h | 3 +- slirp/tcp_input.c | 95 +++--- slirp/tcp_output.c | 29 - slirp/tcp_subr.c | 50 ++-- 4 files changed, 89 insertions(+), 88 deletions(-) diff --git a/slirp/slirp.h b/slirp/slirp.h index 6c06505..3cdf984 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -365,7 +365,8 @@ void tcp_setpersist(register struct tcpcb *); void tcp_init(Slirp *); void tcp_cleanup(Slirp *); void tcp_template(struct tcpcb *); -void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int, sa_family_t); +void tcp_respond(struct tcpcb *, register struct tcpiphdr *, +register struct mbuf *, tcp_seq, tcp_seq, int, sa_family_t); struct tcpcb * tcp_newtcpcb(struct socket *); struct tcpcb * tcp_close(register struct tcpcb *); void tcp_sockclosed(struct tcpcb *); diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c index 48b7fc6..3409557 100644 --- a/slirp/tcp_input.c +++ b/slirp/tcp_input.c @@ -256,48 +256,48 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, sa_family_t af) switch (af) { case AF_INET: - if (iphlen sizeof(struct ip )) { - ip_stripoptions(m, (struct mbuf *)0); - iphlen=sizeof(struct ip ); - } - /* XXX Check if too short */ + if (iphlen sizeof(struct ip)) { + ip_stripoptions(m, (struct mbuf *)0); + iphlen = sizeof(struct ip); + } + /* XXX Check if too short */ - /* -* Save a copy of the IP header in case we want restore it -* for sending an ICMP error message in response. -*/ - ip=mtod(m, struct ip *); - save_ip = *ip; - save_ip.ip_len+= iphlen; + /* +* Save a copy of the IP header in case we want restore it +* for sending an ICMP error message in response. +*/ + ip = mtod(m, struct ip *); + save_ip = *ip; + save_ip.ip_len += iphlen; - /* -* Get IP and TCP header together in first mbuf. -* Note: IP leaves IP header in first mbuf. -*/ - m-m_data -= sizeof(struct tcpiphdr) - (sizeof(struct ip) -+ sizeof(struct tcphdr)); - m-m_len += sizeof(struct tcpiphdr) - (sizeof(struct ip) - + sizeof(struct tcphdr)); - ti = mtod(m, struct tcpiphdr *); + /* +* Get IP and TCP header together in first mbuf. +* Note: IP leaves IP header in first mbuf. +*/ + m-m_data -= sizeof(struct tcpiphdr) - (sizeof(struct ip) ++ sizeof(struct tcphdr)); + m-m_len += sizeof(struct tcpiphdr) - (sizeof(struct ip) ++ sizeof(struct tcphdr)); + ti = mtod(m, struct tcpiphdr *); - /* -* Checksum extended TCP header and data. -*/ - tlen = ip-ip_len; - tcpiphdr2qlink(ti)-next = tcpiphdr2qlink(ti)-prev = NULL; - memset(ti-ih_mbuf, 0 , sizeof(struct mbuf_ptr)); - memset(ti-ti, 0, sizeof(ti-ti)); - ti-ti_x0 = 0; - ti-ti_src = save_ip.ip_src; - ti-ti_dst = save_ip.ip_dst; - ti-ti_pr = save_ip.ip_p; - ti-ti_len = htons((uint16_t)tlen); - len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen); - if(cksum(m, len)) { - goto drop; - } - break; + /* +* Checksum extended TCP header and data. +*/ + tlen = ip-ip_len; + tcpiphdr2qlink(ti)-next = tcpiphdr2qlink(ti)-prev = NULL; + memset(ti-ih_mbuf, 0 , sizeof(struct mbuf_ptr)); + memset(ti-ti, 0, sizeof(ti-ti)); + ti-ti_x0 = 0; + ti-ti_src = save_ip.ip_src; + ti-ti_dst = save_ip.ip_dst; + ti-ti_pr = save_ip.ip_p; + ti-ti_len = htons((uint16_t)tlen); + len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen); + if (cksum(m, len)) { + goto drop; + } + break; default: goto drop; @@ -341,10 +341,10 @@ findso: fhost.ss_family = af; switch (af) { case AF_INET: - ((struct sockaddr_in *)lhost)-sin_addr = ti-ti_src; - ((struct sockaddr_in *)lhost)-sin_port = ti-ti_sport; - ((struct sockaddr_in *)fhost)-sin_addr = ti-ti_dst; - ((struct sockaddr_in *)fhost)-sin_port = ti-ti_dport; + ((struct sockaddr_in *)lhost)-sin_addr = ti-ti_src; + ((struct sockaddr_in *)lhost)-sin_port = ti-ti_sport; + ((struct sockaddr_in *)fhost)-sin_addr = ti-ti_dst; + ((struct sockaddr_in
[Qemu-devel] [PATCHv4 00/18] slirp: Adding IPv6 support to Qemu -net user mode
Hello, This is another respin of IPv6 in Qemu -net user mode. These patches add ICMPv6, NDP, and make UDP and TCP compatible with IPv6. We have made some refactoring to make current code compatible with IPv6. Patches 1 to 8 are refactoring of existing code and do not change the behavior, 9 adds a helper, and 10 to 18 add ipv6 support. Patches 3 and 16 are only reindents of the resulting code, without code change. Difference with version 3 is: - reindentation has been moved into separate patches - inet6 support in sockaddr_equal has been moved to the ndp support patch. - update first qemu version for the options Here is a summary of the patches: Refactoring patches: [PATCH 01/18] slirp: goto bad in udp_input if sosendto fails [PATCH 02/18] slirp: Generalizing and neutralizing code before adding [PATCH 03/18] slirp: Reindent after refactoring [PATCH 04/18] slirp: Make Socket structure IPv6 compatible [PATCH 05/18] slirp: Factorizing address translation [PATCH 06/18] slirp: Factorizing and cleaning solookup() [PATCH 07/18] slirp: Make udp_attach IPv6 compatible [PATCH 08/18] slirp: Adding family argument to tcp_fconnect() Adding helper: [PATCH 09/18] qemu/timer.h : Adding function to second scale Adding v6 support: [PATCH 10/18] slirp: Adding IPv6, ICMPv6 Echo and NDP [PATCH 11/18] slirp: Adding ICMPv6 error sending [PATCH 12/18] slirp: Adding IPv6 UDP support [PATCH 13/18] slirp: Factorizing tcpiphdr structure with an union [PATCH 14/18] slirp: Generalizing and neutralizing various TCP [PATCH 15/18] slirp: Reindent after refactoring [PATCH 16/18] slirp: Handle IPv6 in TCP functions [PATCH 17/18] slirp: Adding IPv6 address for DNS relay [PATCH 18/18] qapi-schema, qemu-options slirp: Adding Qemu options
[Qemu-devel] [PATCH 10/18] slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration
This patch adds the functions needed to handle IPv6 packets. ICMPv6 and NDP headers are implemented. Slirp is now able to send NDP Router or Neighbor Advertisement when it receives Router or Neighbor Solicitation. Using a 64bit-sized IPv6 prefix, the guest is now able to perform stateless autoconfiguration (SLAAC) and to compute its IPv6 address. This patch adds an ndp_table, mainly inspired by arp_table, to keep an NDP cache and manage network address resolution. Slirp regularly sends NDP Neighbor Advertisement, as recommended by the RFC, to make the guest refresh its route. This also adds ip6_cksum() to compute ICMPv6 checksums using IPv6 pseudo-header. Signed-off-by: Guillaume Subiron maet...@subiron.org Signed-off-by: Samuel Thibault samuel.thiba...@ens-lyon.org --- slirp/Makefile.objs | 4 +- slirp/cksum.c | 23 slirp/ip6.h | 139 + slirp/ip6_icmp.c| 349 slirp/ip6_icmp.h| 248 + slirp/ip6_input.c | 75 +++ slirp/ip6_output.c | 41 ++ slirp/ndp_table.c | 87 + slirp/slirp.c | 47 +-- slirp/slirp.h | 35 ++ slirp/socket.h | 7 ++ 11 files changed, 1045 insertions(+), 10 deletions(-) create mode 100644 slirp/ip6.h create mode 100644 slirp/ip6_icmp.c create mode 100644 slirp/ip6_icmp.h create mode 100644 slirp/ip6_input.c create mode 100644 slirp/ip6_output.c create mode 100644 slirp/ndp_table.c diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs index 2daa9dc..2dfe8e0 100644 --- a/slirp/Makefile.objs +++ b/slirp/Makefile.objs @@ -1,3 +1,3 @@ -common-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o dnssearch.o +common-obj-y = cksum.o if.o ip_icmp.o ip6_icmp.o ip6_input.o ip6_output.o ip_input.o ip_output.o dnssearch.o common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o -common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o +common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o ndp_table.o diff --git a/slirp/cksum.c b/slirp/cksum.c index 6328660..f0a1398 100644 --- a/slirp/cksum.c +++ b/slirp/cksum.c @@ -137,3 +137,26 @@ cont: REDUCE; return (~sum 0x); } + +int ip6_cksum(struct mbuf *m) +{ +struct ip6 save_ip, *ip = mtod(m, struct ip6 *); +struct ip6_pseudohdr *ih = mtod(m, struct ip6_pseudohdr *); +int sum; + +save_ip = *ip; + +ih-ih_src = save_ip.ip_src; +ih-ih_dst = save_ip.ip_dst; +ih-ih_pl = htonl((uint32_t)ntohs(save_ip.ip_pl)); +ih-ih_zero_hi = 0; +ih-ih_zero_lo = 0; +ih-ih_nh = save_ip.ip_nh; + +sum = cksum(m, ((int)sizeof(struct ip6_pseudohdr)) ++ ntohl(ih-ih_pl)); + +*ip = save_ip; + +return sum; +} diff --git a/slirp/ip6.h b/slirp/ip6.h new file mode 100644 index 000..9e65acd --- /dev/null +++ b/slirp/ip6.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2013 + * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. + * + * Please read the file COPYRIGHT for the + * terms and conditions of the copyright. + */ + +#ifndef _IP6_H_ +#define _IP6_H_ + +#define in6_multicast(a) IN6_IS_ADDR_MULTICAST((a)) +#define in6_linklocal(a) IN6_IS_ADDR_LINKLOCAL((a)) +#define in6_unspecified(a) IN6_IS_ADDR_UNSPECIFIED((a)) + +#define ALLNODES_MULTICAST { .s6_addr = \ +{ 0xff, 0x02, 0x00, 0x00,\ +0x00, 0x00, 0x00, 0x00,\ +0x00, 0x00, 0x00, 0x00,\ +0x00, 0x00, 0x00, 0x01 } } + +#define SOLICITED_NODE_PREFIX { .s6_addr = \ +{ 0xff, 0x02, 0x00, 0x00,\ +0x00, 0x00, 0x00, 0x00,\ +0x00, 0x00, 0x00, 0x01,\ +0xff, 0x00, 0x00, 0x00 } } + +#define LINKLOCAL_ADDR { .s6_addr = \ +{ 0xfe, 0x80, 0x00, 0x00,\ +0x00, 0x00, 0x00, 0x00,\ +0x00, 0x00, 0x00, 0x00,\ +0x00, 0x00, 0x00, 0x02 } } + +static inline int in6_equal(struct in6_addr a, struct in6_addr b) +{ +return memcmp(a, b, sizeof(a)) == 0; +} + +static inline int in6_equal_net(struct in6_addr a, struct in6_addr b, +int prefix_len) +{ +if (memcmp(a, b, prefix_len / 8) != 0) { +return 0; +} + +if (prefix_len % 8 == 0) { +return 1; +} + +return (a.s6_addr[prefix_len / 8] (8 - (prefix_len % 8))) +== (b.s6_addr[prefix_len / 8] (8 - (prefix_len % 8))); +} + +static inline int in6_equal_mach(struct in6_addr a, struct in6_addr b, +int prefix_len) +{ +if (memcmp((a.s6_addr[(prefix_len + 7) / 8]), +(b.s6_addr[(prefix_len + 7) / 8]), +16 - (prefix_len + 7) / 8) != 0) { +return 0; +} + +if (prefix_len % 8 == 0) { +return 1; +} + +return (a.s6_addr[prefix_len / 8]
[Qemu-devel] [PATCH 11/18] slirp: Adding ICMPv6 error sending
Disambiguation : icmp_error is renamed into icmp_send_error, since it doesn't manage errors, but only sends ICMP Error messages. Adding icmp6_send_error to send ICMPv6 Error messages. This function is simpler than the v4 version. Adding some calls in various functions to send ICMP errors, when a received packet is too big, or when its hop limit is 0. Signed-off-by: Yann Bordenave m...@meowstars.org --- slirp/ip6_icmp.c | 60 +++ slirp/ip6_icmp.h | 10 ++ slirp/ip6_input.c | 16 --- slirp/ip_icmp.c | 12 +-- slirp/ip_icmp.h | 4 ++-- slirp/ip_input.c | 8 slirp/socket.c| 4 ++-- slirp/tcp_input.c | 2 +- slirp/udp.c | 3 ++- 9 files changed, 96 insertions(+), 23 deletions(-) diff --git a/slirp/ip6_icmp.c b/slirp/ip6_icmp.c index 4538bfd..8952bbc 100644 --- a/slirp/ip6_icmp.c +++ b/slirp/ip6_icmp.c @@ -64,6 +64,66 @@ static void icmp6_send_echoreply(struct mbuf *m, Slirp *slirp, struct ip6 *ip, ip6_output(NULL, t, 0); } +void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code) +{ +Slirp *slirp = m-slirp; +struct mbuf *t = m_get(slirp); +struct ip6 *ip = mtod(m, struct ip6 *); + +char addrstr[INET6_ADDRSTRLEN]; +DEBUG_CALL(icmp_send_error); +DEBUG_ARGS((dfd, type = %d, code = %d\n, type, code)); + +/* IPv6 packet */ +struct ip6 *rip = mtod(t, struct ip6 *); +rip-ip_src = (struct in6_addr)LINKLOCAL_ADDR; +if (in6_multicast(ip-ip_src) || in6_unspecified(ip-ip_src)) { +/* :TODO:maethor:130317: icmp error? */ +return; +} +rip-ip_dst = ip-ip_src; +inet_ntop(AF_INET6, rip-ip_dst, addrstr, INET6_ADDRSTRLEN); +DEBUG_ARG(target = %s, addrstr); + +rip-ip_nh = IPPROTO_ICMPV6; +const int error_data_len = min(m-m_len, +IF_MTU - (sizeof(struct ip6) + ICMP6_ERROR_MINLEN)); +rip-ip_pl = htons(ICMP6_ERROR_MINLEN + error_data_len); +t-m_len = sizeof(struct ip6) + ntohs(rip-ip_pl); + +/* ICMPv6 packet */ +t-m_data += sizeof(struct ip6); +struct icmp6 *ricmp = mtod(t, struct icmp6 *); +ricmp-icmp6_type = type; +ricmp-icmp6_code = code; +ricmp-icmp6_cksum = 0; + +switch (type) { +case ICMP6_UNREACH: +case ICMP6_TIMXCEED: +ricmp-icmp6_err.unused = 0; +break; +case ICMP6_TOOBIG: +ricmp-icmp6_err.mtu = htonl(IF_MTU); +break; +case ICMP6_PARAMPROB: +/* :TODO:Meow:130316: Handle this case */ +break; +default: +assert(0); +break; +} +t-m_data += ICMP6_ERROR_MINLEN; +memcpy(t-m_data, m-m_data, error_data_len); + +/* Checksum */ +t-m_data -= ICMP6_ERROR_MINLEN; +t-m_data -= sizeof(struct ip6); +ricmp-icmp6_cksum = ip6_cksum(t); + +ip6_output(NULL, t, 0); +} + /* * Process a NDP message */ diff --git a/slirp/ip6_icmp.h b/slirp/ip6_icmp.h index bd9d3d9..deae1a1 100644 --- a/slirp/ip6_icmp.h +++ b/slirp/ip6_icmp.h @@ -22,6 +22,12 @@ struct icmp6_echo { /* Echo Messages */ uint16_t seq_num; }; +union icmp6_error_body { +uint32_t unused; +uint32_t pointer; +uint32_t mtu; +}; + /* * NDP Messages */ @@ -85,6 +91,7 @@ struct icmp6 { uint8_t icmp6_code; /* type sub code */ uint16_ticmp6_cksum;/* ones complement cksum of struct */ union { +union icmp6_error_body error_body; struct icmp6_echo echo; struct ndp_rs ndp_rs; struct ndp_ra ndp_ra; @@ -92,6 +99,7 @@ struct icmp6 { struct ndp_na ndp_na; struct ndp_redirect ndp_redirect; } icmp6_body; +#define icmp6_err icmp6_body.error_body #define icmp6_echo icmp6_body.echo #define icmp6_nrs icmp6_body.ndp_rs #define icmp6_nra icmp6_body.ndp_ra @@ -101,6 +109,7 @@ struct icmp6 { } QEMU_PACKED; #define ICMP6_MINLEN4 +#define ICMP6_ERROR_MINLEN 8 #define ICMP6_ECHO_MINLEN 8 #define ICMP6_NDP_RS_MINLEN 8 #define ICMP6_NDP_RA_MINLEN 16 @@ -242,6 +251,7 @@ void icmp6_input(struct mbuf *); void icmp6_error(struct mbuf *msrc, u_char type, u_char code, int minsize, const char *message); */ +void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code); void ndp_send_ra(Slirp *slirp); void ndp_send_ns(Slirp *slirp, struct in6_addr addr); diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c index 9663c42..af098a5 100644 --- a/slirp/ip6_input.c +++ b/slirp/ip6_input.c @@ -33,7 +33,7 @@ void ip6_input(struct mbuf *m) DEBUG_ARG(m_len = %d, m-m_len); if (m-m_len sizeof(struct ip6)) { -return; +goto bad; } ip6 = mtod(m, struct ip6 *); @@ -42,10 +42,14 @@ void ip6_input(struct mbuf *m) goto bad; } +if (ntohs(ip6-ip_pl) IF_MTU) { +icmp6_send_error(m, ICMP6_TOOBIG, 0); +goto bad; +} + /* check ip_ttl for a correct ICMP reply */ if (ip6-ip_hl == 0) { -/* :TODO:maethor:130307: icmp6_error
[Qemu-devel] [PATCH 06/18] slirp: Factorizing and cleaning solookup()
This patch makes solookup() compatible with varying address families. Also, this function was only compatible with TCP. Having the socket list in argument, it is now compatible with UDP too. Finally, some optimization code is factorized inside the function (the function look at the last returned result before browsing the complete socket list). This also adds a sockaddr_equal() function to compare two sockaddr_storage. Signed-off-by: Guillaume Subiron maet...@subiron.org --- slirp/socket.c| 30 -- slirp/socket.h| 23 ++- slirp/tcp_input.c | 27 +++ slirp/udp.c | 25 ++--- 4 files changed, 55 insertions(+), 50 deletions(-) diff --git a/slirp/socket.c b/slirp/socket.c index c0c8bc1..0e37a52 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -15,24 +15,26 @@ static void sofcantrcvmore(struct socket *so); static void sofcantsendmore(struct socket *so); -struct socket * -solookup(struct socket *head, struct in_addr laddr, u_int lport, - struct in_addr faddr, u_int fport) +struct socket *solookup(struct socket **last, struct socket *head, +struct sockaddr_storage *lhost, struct sockaddr_storage *fhost) { - struct socket *so; +struct socket *so = *last; - for (so = head-so_next; so != head; so = so-so_next) { - if (so-so_lport == lport - so-so_laddr.s_addr == laddr.s_addr - so-so_faddr.s_addr == faddr.s_addr - so-so_fport == fport) - break; - } +/* Optimisation */ +if (sockaddr_equal((so-lhost.ss), lhost) + (!fhost || sockaddr_equal((so-fhost.ss), fhost))) { +return so; +} - if (so == head) - return (struct socket *)NULL; - return so; +for (so = head-so_next; so != head; so = so-so_next) { +if (sockaddr_equal((so-lhost.ss), lhost) + (!fhost || sockaddr_equal((so-fhost.ss), fhost))) { +*last = so; +return so; +} +} +return (struct socket *)NULL; } /* diff --git a/slirp/socket.h b/slirp/socket.h index 50059be..5a673ae 100644 --- a/slirp/socket.h +++ b/slirp/socket.h @@ -93,7 +93,28 @@ struct socket { #define SS_HOSTFWD 0x1000 /* Socket describes host-guest forwarding */ #define SS_INCOMING0x2000 /* Connection was initiated by a host on the internet */ -struct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int); +static inline int sockaddr_equal(struct sockaddr_storage *a, +struct sockaddr_storage *b) +{ +if (a-ss_family != b-ss_family) { +return 0; +} else { +switch (a-ss_family) { +case AF_INET: +{ +struct sockaddr_in *a4 = (struct sockaddr_in *) a; +struct sockaddr_in *b4 = (struct sockaddr_in *) b; +return (a4-sin_addr.s_addr == b4-sin_addr.s_addr + a4-sin_port == b4-sin_port); +} +default: +assert(0); +} +} +} + +struct socket *solookup(struct socket **, struct socket *, +struct sockaddr_storage *, struct sockaddr_storage *); struct socket * socreate(Slirp *); void sofree(struct socket *); int soread(struct socket *); diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c index 4b1a383..1b9a0b1 100644 --- a/slirp/tcp_input.c +++ b/slirp/tcp_input.c @@ -227,6 +227,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso) int iss = 0; u_long tiwin; int ret; + struct sockaddr_storage lhost, fhost; struct ex_list *ex_ptr; Slirp *slirp; @@ -320,16 +321,14 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso) * Locate pcb for segment. */ findso: - so = slirp-tcp_last_so; - if (so-so_fport != ti-ti_dport || - so-so_lport != ti-ti_sport || - so-so_laddr.s_addr != ti-ti_src.s_addr || - so-so_faddr.s_addr != ti-ti_dst.s_addr) { - so = solookup(slirp-tcb, ti-ti_src, ti-ti_sport, - ti-ti_dst, ti-ti_dport); - if (so) - slirp-tcp_last_so = so; - } + lhost.ss_family = AF_INET; + ((struct sockaddr_in *)lhost)-sin_addr = ti-ti_src; + ((struct sockaddr_in *)lhost)-sin_port = ti-ti_sport; + fhost.ss_family = AF_INET; + ((struct sockaddr_in *)fhost)-sin_addr = ti-ti_dst; + ((struct sockaddr_in *)fhost)-sin_port = ti-ti_dport; + + so = solookup(slirp-tcp_last_so, slirp-tcb, lhost, fhost); /* * If the state is CLOSED (i.e., TCB does not exist) then @@ -374,12 +373,8 @@ findso: sbreserve(so-so_snd, TCP_SNDSPACE); sbreserve(so-so_rcv, TCP_RCVSPACE); - so-so_lfamily = AF_INET; - so-so_laddr = ti-ti_src; - so-so_lport = ti-ti_sport; - so-so_ffamily =
[Qemu-devel] [PATCH 13/18] slirp: Factorizing tcpiphdr structure with an union
This patch factorizes the tcpiphdr structure to put the IPv4 fields in an union, for addition of version 6 in further patch. Using some macros, retrocompatibility of the existing code is assured. This patch also fixes the SLIRP_MSIZE and margin computation in various functions, and makes them compatible with the new tcpiphdr structure, whose size will be bigger than sizeof(struct tcphdr) + sizeof(struct ip) Signed-off-by: Guillaume Subiron maet...@subiron.org Signed-off-by: Samuel Thibault samuel.thiba...@ens-lyon.org --- slirp/if.h | 4 ++-- slirp/mbuf.c | 3 ++- slirp/slirp.c | 15 --- slirp/socket.c | 13 - slirp/tcp_input.c | 31 --- slirp/tcp_output.c | 18 +- slirp/tcp_subr.c | 31 ++- slirp/tcpip.h | 31 +++ 8 files changed, 102 insertions(+), 44 deletions(-) diff --git a/slirp/if.h b/slirp/if.h index 3327023..c7a5c57 100644 --- a/slirp/if.h +++ b/slirp/if.h @@ -17,7 +17,7 @@ #define IF_MRU 1500 #defineIF_COMP IF_AUTOCOMP /* Flags for compression */ -/* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ -#define IF_MAXLINKHDR (2 + 14 + 40) +/* 2 for alignment, 14 for ethernet */ +#define IF_MAXLINKHDR (2 + ETH_HLEN) #endif diff --git a/slirp/mbuf.c b/slirp/mbuf.c index 92c429e..87ee550 100644 --- a/slirp/mbuf.c +++ b/slirp/mbuf.c @@ -23,7 +23,8 @@ * Find a nice value for msize * XXX if_maxlinkhdr already in mtu */ -#define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + offsetof(struct mbuf, m_dat) + 6) +#define SLIRP_MSIZE\ +(offsetof(struct mbuf, m_dat) + IF_MAXLINKHDR + TCPIPHDR_DELTA + IF_MTU) void m_init(Slirp *slirp) diff --git a/slirp/slirp.c b/slirp/slirp.c index eea2fee..33ed0cd 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -756,15 +756,16 @@ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) m = m_get(slirp); if (!m) return; -/* Note: we add to align the IP header */ -if (M_FREEROOM(m) pkt_len + 2) { -m_inc(m, pkt_len + 2); +/* Note: we add 2 to align the IP header on 4 bytes, + * and add the margin for the tcpiphdr overhead */ +if (M_FREEROOM(m) pkt_len + TCPIPHDR_DELTA + 2) { +m_inc(m, pkt_len + TCPIPHDR_DELTA + 2); } -m-m_len = pkt_len + 2; -memcpy(m-m_data + 2, pkt, pkt_len); +m-m_len = pkt_len + TCPIPHDR_DELTA + 2; +memcpy(m-m_data + TCPIPHDR_DELTA + 2, pkt, pkt_len); -m-m_data += 2 + ETH_HLEN; -m-m_len -= 2 + ETH_HLEN; +m-m_data += TCPIPHDR_DELTA + 2 + ETH_HLEN; +m-m_len -= TCPIPHDR_DELTA + 2 + ETH_HLEN; if (proto == ETH_P_IP) { ip_input(m); diff --git a/slirp/socket.c b/slirp/socket.c index 31bbb7e..567f9bc 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -482,7 +482,18 @@ sorecvfrom(struct socket *so) if (!m) { return; } - m-m_data += IF_MAXLINKHDR; + switch (so-so_ffamily) { + case AF_INET: + m-m_data += IF_MAXLINKHDR + sizeof(struct udpiphdr); + break; + case AF_INET6: + m-m_data += IF_MAXLINKHDR + sizeof(struct ip6) ++ sizeof(struct udphdr); + break; + default: + assert(0); + break; + } /* * XXX Shouldn't FIONREAD packets destined for port 53, diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c index 25929bd..dde89b6 100644 --- a/slirp/tcp_input.c +++ b/slirp/tcp_input.c @@ -254,11 +254,6 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso) } slirp = m-slirp; - /* -* Get IP and TCP header together in first mbuf. -* Note: IP leaves IP header in first mbuf. -*/ - ti = mtod(m, struct tcpiphdr *); if (iphlen sizeof(struct ip )) { ip_stripoptions(m, (struct mbuf *)0); iphlen=sizeof(struct ip ); @@ -275,14 +270,28 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso) save_ip.ip_len+= iphlen; /* +* Get IP and TCP header together in first mbuf. +* Note: IP leaves IP header in first mbuf. +*/ + m-m_data -= sizeof(struct tcpiphdr) - (sizeof(struct ip) ++ sizeof(struct tcphdr)); + m-m_len += sizeof(struct tcpiphdr) - (sizeof(struct ip) + + sizeof(struct tcphdr)); + ti = mtod(m, struct tcpiphdr *); + + /* * Checksum extended TCP header and data. */ - tlen = ((struct ip *)ti)-ip_len; -tcpiphdr2qlink(ti)-next = tcpiphdr2qlink(ti)-prev = NULL; -memset(ti-ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr)); - ti-ti_x1 = 0; + tlen = ip-ip_len; + tcpiphdr2qlink(ti)-next =
[Qemu-devel] [PATCH 17/18] slirp: Adding IPv6 address for DNS relay
This patch adds an IPv6 address to the DNS relay. in6_equal_dns() is developed using this Slirp attribute. sotranslate_in/out() are also updated to manage the IPv6 case so the guest can be able to join the host using one of the Slirp addresses. Signed-off-by: Guillaume Subiron maet...@subiron.org --- slirp/ip6.h| 5 - slirp/slirp.c | 2 ++ slirp/slirp.h | 1 + slirp/socket.c | 26 -- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/slirp/ip6.h b/slirp/ip6.h index 9e65acd..c799421 100644 --- a/slirp/ip6.h +++ b/slirp/ip6.h @@ -74,7 +74,10 @@ static inline int in6_equal_mach(struct in6_addr a, struct in6_addr b, || (in6_equal_net(a, (struct in6_addr)LINKLOCAL_ADDR, 64)\ in6_equal_mach(a, slirp-vhost_addr6, 64))) -#define in6_equal_dns(a) 0 +#define in6_equal_dns(a)\ +((in6_equal_net(a, slirp-vprefix_addr6, slirp-vprefix_len)\ + || in6_equal_net(a, (struct in6_addr)LINKLOCAL_ADDR, 64))\ + in6_equal_mach(a, slirp-vnameserver_addr6, slirp-vprefix_len)) #define in6_equal_host(a)\ (in6_equal_router(a) || in6_equal_dns(a)) diff --git a/slirp/slirp.c b/slirp/slirp.c index 7f2ed70..ce3a111 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -236,6 +236,8 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, slirp-bootp_filename = g_strdup(bootfile); slirp-vdhcp_startaddr = vdhcp_start; slirp-vnameserver_addr = vnameserver; +/* :TODO:maethor:130311: Use a parameter passed to the function */ +inet_pton(AF_INET6, fec0::3, slirp-vnameserver_addr6); if (vdnssearch) { translate_dnssearch(slirp, vdnssearch); diff --git a/slirp/slirp.h b/slirp/slirp.h index 3cdf984..57fe17e 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -236,6 +236,7 @@ struct Slirp { struct in6_addr vhost_addr6; struct in_addr vdhcp_startaddr; struct in_addr vnameserver_addr; +struct in6_addr vnameserver_addr6; struct in_addr client_ipaddr; char client_hostname[33]; diff --git a/slirp/socket.c b/slirp/socket.c index 567f9bc..a9b3957 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -741,12 +741,12 @@ sofwdrain(struct socket *so) /* * Translate addr in host addr when it is a virtual address - * :TODO:maethor:130314: Manage IPv6 */ void sotranslate_out(struct socket *so, struct sockaddr_storage *addr) { Slirp *slirp = so-slirp; struct sockaddr_in *sin = (struct sockaddr_in *)addr; +struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; switch (addr-ss_family) { case AF_INET: @@ -767,16 +767,29 @@ void sotranslate_out(struct socket *so, struct sockaddr_storage *addr) ntohs(sin-sin_port), inet_ntoa(sin-sin_addr))); break; +case AF_INET6: +if (in6_equal_net(so-so_faddr6, slirp-vprefix_addr6, +slirp-vprefix_len)) { +if (in6_equal(so-so_faddr6, slirp-vnameserver_addr6)) { +/*if (get_dns_addr(addr) 0) {*/ /* TODO */ +sin6-sin6_addr = in6addr_loopback; +/*}*/ +} else { +sin6-sin6_addr = in6addr_loopback; +} +} +break; + default: break; } } -/* :TODO:maethor:130314: IPv6 */ void sotranslate_in(struct socket *so, struct sockaddr_storage *addr) { Slirp *slirp = so-slirp; struct sockaddr_in *sin = (struct sockaddr_in *)addr; +struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; switch (addr-ss_family) { case AF_INET: @@ -793,6 +806,15 @@ void sotranslate_in(struct socket *so, struct sockaddr_storage *addr) } break; +case AF_INET6: +if (in6_equal_net(so-so_faddr6, slirp-vprefix_addr6, +slirp-vprefix_len)) { +if (in6_equal(sin6-sin6_addr, in6addr_loopback) +|| !in6_equal(so-so_faddr6, slirp-vhost_addr6)) { +sin6-sin6_addr = so-so_faddr6; +} +} + default: break; } -- 1.9.0
Re: [Qemu-devel] [PATCH v2] target-ppc: improve info registers by printing SPRs
On 03/24/2014 05:24 PM, Alexey Kardashevskiy wrote: On 03/23/2014 01:43 AM, Stuart Brady wrote: On Sat, Mar 22, 2014 at 11:25:49PM +1100, Alexey Kardashevskiy wrote: This adds printing of all SPR registers registered for a CPU. This removes SPR_ prefix from SPR name to reduce the output. Cc: Fabien Chouteau chout...@adacore.com Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru --- Changes: v2: * removed switch (env-mmu_model) * added \n if the last line has less than 4 registers --- target-ppc/translate.c | 96 +++-- target-ppc/translate_init.c | 40 +-- 2 files changed, 35 insertions(+), 101 deletions(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index e3fcb03..06f195a 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -6,7 +6,7 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, PowerPCCPU *cpu = POWERPC_CPU(cs); CPUPPCState *env = cpu-env; -int i; +int i, j; cpu_fprintf(f, NIP TARGET_FMT_lxLR TARGET_FMT_lx CTR TARGET_FMT_lx XER TARGET_FMT_lx \n, @@ -11167,54 +11167,22 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf(f, \n); } cpu_fprintf(f, FPSCR TARGET_FMT_lx \n, env-fpscr); -#if !defined(CONFIG_USER_ONLY) -cpu_fprintf(f, SRR0 TARGET_FMT_lx SRR1 TARGET_FMT_lx - PVR TARGET_FMT_lx VRSAVE TARGET_FMT_lx \n, -env-spr[SPR_SRR0], env-spr[SPR_SRR1], -env-spr[SPR_PVR], env-spr[SPR_VRSAVE]); -cpu_fprintf(f, SPRG0 TARGET_FMT_lx SPRG1 TARGET_FMT_lx - SPRG2 TARGET_FMT_lx SPRG3 TARGET_FMT_lx \n, -env-spr[SPR_SPRG0], env-spr[SPR_SPRG1], -env-spr[SPR_SPRG2], env-spr[SPR_SPRG3]); - -cpu_fprintf(f, SPRG4 TARGET_FMT_lx SPRG5 TARGET_FMT_lx - SPRG6 TARGET_FMT_lx SPRG7 TARGET_FMT_lx \n, -env-spr[SPR_SPRG4], env-spr[SPR_SPRG5], -env-spr[SPR_SPRG6], env-spr[SPR_SPRG7]); - -if (env-excp_model == POWERPC_EXCP_BOOKE) { -cpu_fprintf(f, CSRR0 TARGET_FMT_lx CSRR1 TARGET_FMT_lx -MCSRR0 TARGET_FMT_lx MCSRR1 TARGET_FMT_lx \n, -env-spr[SPR_BOOKE_CSRR0], env-spr[SPR_BOOKE_CSRR1], -env-spr[SPR_BOOKE_MCSRR0], env-spr[SPR_BOOKE_MCSRR1]); - -cpu_fprintf(f, TCR TARGET_FMT_lxTSR TARGET_FMT_lx - ESR TARGET_FMT_lxDEAR TARGET_FMT_lx \n, -env-spr[SPR_BOOKE_TCR], env-spr[SPR_BOOKE_TSR], -env-spr[SPR_BOOKE_ESR], env-spr[SPR_BOOKE_DEAR]); - -cpu_fprintf(f, PIR TARGET_FMT_lx DECAR TARGET_FMT_lx - IVPR TARGET_FMT_lxEPCR TARGET_FMT_lx \n, -env-spr[SPR_BOOKE_PIR], env-spr[SPR_BOOKE_DECAR], -env-spr[SPR_BOOKE_IVPR], env-spr[SPR_BOOKE_EPCR]); - -cpu_fprintf(f, MCSR TARGET_FMT_lx SPRG8 TARGET_FMT_lx - EPR TARGET_FMT_lx \n, -env-spr[SPR_BOOKE_MCSR], env-spr[SPR_BOOKE_SPRG8], -env-spr[SPR_BOOKE_EPR]); - -/* FSL-specific */ -cpu_fprintf(f, MCAR TARGET_FMT_lx PID1 TARGET_FMT_lx - PID2 TARGET_FMT_lx SVR TARGET_FMT_lx \n, -env-spr[SPR_Exxx_MCAR], env-spr[SPR_BOOKE_PID1], -env-spr[SPR_BOOKE_PID2], env-spr[SPR_E500_SVR]); - -/* - * IVORs are left out as they are large and do not change often -- - * they can be read with p $ivor0, p $ivor1, etc. - */ +for (i = 0, j = 0; i ARRAY_SIZE(env-spr_cb); i++) { +ppc_spr_t *spr = env-spr_cb[i]; + +if (!spr-name) { +continue; +} This would leave the output without a trailing newline if the last spr doesn't have a name registered. Is it necessary to handle unnamed sprs at all (maybe add an assert to the registration function)? ... or would we just want to warn about them here? In the current QEMU I do not see any place where SPR would be registered without a name so I would not bother. FWIW, my approach is often to write an outer loop that process one item of output at a time, with an inner loop to obtain the next item of data, and with prefixing of separators, as you then have a far simpler special case for 'j == 0' instead of 'i == ARRAY_SIZE(env-spr_cb) - 1'. You can then unconditionally finish on a '\n'. Oh. This is embarrassing, sorry :( This should do it, right? :) +for (i = 0, j = 0; i ARRAY_SIZE(env-spr_cb); i++) { +ppc_spr_t *spr = env-spr_cb[i]; + +if (!spr-name) { +continue; +} +if (j % 4) { +
Re: [Qemu-devel] [PATCH v2 2/5] target-i386: Implement nmi() callback
On 03/28/2014 11:51 PM, Alexey Kardashevskiy wrote: Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru --- target-i386/cpu.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 8fd1497..35f20e0 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2489,6 +2489,19 @@ static void x86_cpu_reset(CPUState *s) #endif } +static int x86_cpu_nmi(CPUState *cs) +{ +X86CPU *cpu = X86_CPU(cs); + +if (!cpu-apic_state) { +cpu_interrupt(cs, CPU_INTERRUPT_NMI); +} else { +apic_deliver_nmi(cpu-apic_state); This symbols is undefined for (i386|x86_64)-linux-user. What would be the right fix here? #ifndef CONFIG_USER_ONLY here or empty stub for apic_deliver_nmi() in include/hw/i386/apic.h? Thanks. +} + +return 0; +} + #ifndef CONFIG_USER_ONLY bool cpu_is_bsp(X86CPU *cpu) { @@ -2797,6 +2810,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) xcc-parent_reset = cc-reset; cc-reset = x86_cpu_reset; +cc-nmi = x86_cpu_nmi; cc-reset_dump_flags = CPU_DUMP_FPU | CPU_DUMP_CCOP; cc-class_by_name = x86_cpu_class_by_name; -- Alexey
Re: [Qemu-devel] [PATCH 0/8] tcg: tidy the type of code_ptr
On 03/30/2014 08:31 AM, Richard Henderson wrote: On 03/29/2014 01:26 PM, Peter Maydell wrote: It seems like it might be worth abstracting out give me the byte difference between these two code pointers rather than having inline (uintptr_t)codeptr1 - (uintptr_t)codeptr2, but I dunno. Yeah, I dithered about that. I couldn't come up with a good name that adequately described what I wanted that was really any shorter than just having the casts. static inline ptrdiff_t tcg_ptr_byte_diff(void *a, void *b) { return a - b; } static inline ptrdiff_t tcg_pcrel_diff(TCGContext *s, void *target) { return tcg_ptr_byte_diff(target, s-code_ptr); } static inline size_t tcg_current_code_size(TCGContext *s) { return tcg_ptr_byte_diff(s-code_ptr, s-code_buf); } Is there a better name than 'tcg_itype' ? Putting 'type' in the name of a type is a bit redundant, and suggests it contains a type rather than an insn. I'm open to suggestions there as well. On x86 and ia64, it won't hold an entire insn, so tcg_insn seemed inappropriate. tcg_{isa,insn}_{part,elt} ? r~
Re: [Qemu-devel] [PATCH v2 2/5] target-i386: Implement nmi() callback
On 03/30/2014 07:55 PM, Alexey Kardashevskiy wrote: On 03/28/2014 11:51 PM, Alexey Kardashevskiy wrote: Signed-off-by: Alexey Kardashevskiy a...@ozlabs.ru --- target-i386/cpu.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 8fd1497..35f20e0 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2489,6 +2489,19 @@ static void x86_cpu_reset(CPUState *s) #endif } +static int x86_cpu_nmi(CPUState *cs) +{ +X86CPU *cpu = X86_CPU(cs); + +if (!cpu-apic_state) { +cpu_interrupt(cs, CPU_INTERRUPT_NMI); +} else { +apic_deliver_nmi(cpu-apic_state); This symbols is undefined for (i386|x86_64)-linux-user. What would be the right fix here? #ifndef CONFIG_USER_ONLY here or empty stub for apic_deliver_nmi() in include/hw/i386/apic.h? Thanks. The ifndef is the normal solution. r~