Loading QMP/qmp.py +40 −14 Original line number Diff line number Diff line Loading @@ -22,19 +22,24 @@ class QMPCapabilitiesError(QMPError): pass class QEMUMonitorProtocol: def __init__(self, address): def __init__(self, address, server=False): """ Create a QEMUMonitorProtocol class. @param address: QEMU address, can be either a unix socket path (string) or a tuple in the form ( address, port ) for a TCP connection @note No connection is established, this is done by the connect() method @param server: server mode listens on the socket (bool) @raise socket.error on socket connection errors @note No connection is established, this is done by the connect() or accept() methods """ self.__events = [] self.__address = address self.__sock = self.__get_sock() self.__sockfile = self.__sock.makefile() if server: self.__sock.bind(self.__address) self.__sock.listen(1) def __get_sock(self): if isinstance(self.__address, tuple): Loading @@ -43,7 +48,18 @@ class QEMUMonitorProtocol: family = socket.AF_UNIX return socket.socket(family, socket.SOCK_STREAM) def __json_read(self): def __negotiate_capabilities(self): self.__sockfile = self.__sock.makefile() greeting = self.__json_read() if greeting is None or not greeting.has_key('QMP'): raise QMPConnectError # Greeting seems ok, negotiate capabilities resp = self.cmd('qmp_capabilities') if "return" in resp: return greeting raise QMPCapabilitiesError def __json_read(self, only_event=False): while True: data = self.__sockfile.readline() if not data: Loading @@ -51,6 +67,7 @@ class QEMUMonitorProtocol: resp = json.loads(data) if 'event' in resp: self.__events.append(resp) if not only_event: continue return resp Loading @@ -66,14 +83,19 @@ class QEMUMonitorProtocol: @raise QMPCapabilitiesError if fails to negotiate capabilities """ self.__sock.connect(self.__address) greeting = self.__json_read() if greeting is None or not greeting.has_key('QMP'): raise QMPConnectError # Greeting seems ok, negotiate capabilities resp = self.cmd('qmp_capabilities') if "return" in resp: return greeting raise QMPCapabilitiesError return self.__negotiate_capabilities() def accept(self): """ Await connection from QMP Monitor and perform capabilities negotiation. @return QMP greeting dict @raise socket.error on socket connection errors @raise QMPConnectError if the greeting is not received @raise QMPCapabilitiesError if fails to negotiate capabilities """ self.__sock, _ = self.__sock.accept() return self.__negotiate_capabilities() def cmd_obj(self, qmp_cmd): """ Loading Loading @@ -106,9 +128,11 @@ class QEMUMonitorProtocol: qmp_cmd['id'] = id return self.cmd_obj(qmp_cmd) def get_events(self): def get_events(self, wait=False): """ Get a list of available QMP events. @param wait: block until an event is available (bool) """ self.__sock.setblocking(0) try: Loading @@ -118,6 +142,8 @@ class QEMUMonitorProtocol: # No data available pass self.__sock.setblocking(1) if not self.__events and wait: self.__json_read(only_event=True) return self.__events def clear_events(self): Loading hmp-commands.hx +5 −4 Original line number Diff line number Diff line Loading @@ -740,10 +740,11 @@ ETEXI #if defined(TARGET_I386) { .name = "nmi", .args_type = "cpu_index:i", .params = "cpu", .help = "inject an NMI on the given CPU", .mhandler.cmd = do_inject_nmi, .args_type = "", .params = "", .help = "inject an NMI on all guest's CPUs", .user_print = monitor_user_noop, .mhandler.cmd_new = do_inject_nmi, }, #endif STEXI Loading monitor.c +12 −7 Original line number Diff line number Diff line Loading @@ -2544,16 +2544,21 @@ static void do_wav_capture(Monitor *mon, const QDict *qdict) #endif #if defined(TARGET_I386) static void do_inject_nmi(Monitor *mon, const QDict *qdict) static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data) { CPUState *env; int cpu_index = qdict_get_int(qdict, "cpu_index"); for (env = first_cpu; env != NULL; env = env->next_cpu) if (env->cpu_index == cpu_index) { for (env = first_cpu; env != NULL; env = env->next_cpu) { cpu_interrupt(env, CPU_INTERRUPT_NMI); break; } return 0; } #else static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data) { qerror_report(QERR_UNSUPPORTED); return -1; } #endif Loading qerror.c +4 −0 Original line number Diff line number Diff line Loading @@ -200,6 +200,10 @@ static const QErrorStringTable qerror_table[] = { .error_fmt = QERR_UNDEFINED_ERROR, .desc = "An undefined error has ocurred", }, { .error_fmt = QERR_UNSUPPORTED, .desc = "this feature or command is not currently supported", }, { .error_fmt = QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, .desc = "'%(device)' uses a %(format) feature which is not " Loading qerror.h +3 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,9 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_UNDEFINED_ERROR \ "{ 'class': 'UndefinedError', 'data': {} }" #define QERR_UNSUPPORTED \ "{ 'class': 'Unsupported', 'data': {} }" #define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \ "{ 'class': 'UnknownBlockFormatFeature', 'data': { 'device': %s, 'format': %s, 'feature': %s } }" Loading Loading
QMP/qmp.py +40 −14 Original line number Diff line number Diff line Loading @@ -22,19 +22,24 @@ class QMPCapabilitiesError(QMPError): pass class QEMUMonitorProtocol: def __init__(self, address): def __init__(self, address, server=False): """ Create a QEMUMonitorProtocol class. @param address: QEMU address, can be either a unix socket path (string) or a tuple in the form ( address, port ) for a TCP connection @note No connection is established, this is done by the connect() method @param server: server mode listens on the socket (bool) @raise socket.error on socket connection errors @note No connection is established, this is done by the connect() or accept() methods """ self.__events = [] self.__address = address self.__sock = self.__get_sock() self.__sockfile = self.__sock.makefile() if server: self.__sock.bind(self.__address) self.__sock.listen(1) def __get_sock(self): if isinstance(self.__address, tuple): Loading @@ -43,7 +48,18 @@ class QEMUMonitorProtocol: family = socket.AF_UNIX return socket.socket(family, socket.SOCK_STREAM) def __json_read(self): def __negotiate_capabilities(self): self.__sockfile = self.__sock.makefile() greeting = self.__json_read() if greeting is None or not greeting.has_key('QMP'): raise QMPConnectError # Greeting seems ok, negotiate capabilities resp = self.cmd('qmp_capabilities') if "return" in resp: return greeting raise QMPCapabilitiesError def __json_read(self, only_event=False): while True: data = self.__sockfile.readline() if not data: Loading @@ -51,6 +67,7 @@ class QEMUMonitorProtocol: resp = json.loads(data) if 'event' in resp: self.__events.append(resp) if not only_event: continue return resp Loading @@ -66,14 +83,19 @@ class QEMUMonitorProtocol: @raise QMPCapabilitiesError if fails to negotiate capabilities """ self.__sock.connect(self.__address) greeting = self.__json_read() if greeting is None or not greeting.has_key('QMP'): raise QMPConnectError # Greeting seems ok, negotiate capabilities resp = self.cmd('qmp_capabilities') if "return" in resp: return greeting raise QMPCapabilitiesError return self.__negotiate_capabilities() def accept(self): """ Await connection from QMP Monitor and perform capabilities negotiation. @return QMP greeting dict @raise socket.error on socket connection errors @raise QMPConnectError if the greeting is not received @raise QMPCapabilitiesError if fails to negotiate capabilities """ self.__sock, _ = self.__sock.accept() return self.__negotiate_capabilities() def cmd_obj(self, qmp_cmd): """ Loading Loading @@ -106,9 +128,11 @@ class QEMUMonitorProtocol: qmp_cmd['id'] = id return self.cmd_obj(qmp_cmd) def get_events(self): def get_events(self, wait=False): """ Get a list of available QMP events. @param wait: block until an event is available (bool) """ self.__sock.setblocking(0) try: Loading @@ -118,6 +142,8 @@ class QEMUMonitorProtocol: # No data available pass self.__sock.setblocking(1) if not self.__events and wait: self.__json_read(only_event=True) return self.__events def clear_events(self): Loading
hmp-commands.hx +5 −4 Original line number Diff line number Diff line Loading @@ -740,10 +740,11 @@ ETEXI #if defined(TARGET_I386) { .name = "nmi", .args_type = "cpu_index:i", .params = "cpu", .help = "inject an NMI on the given CPU", .mhandler.cmd = do_inject_nmi, .args_type = "", .params = "", .help = "inject an NMI on all guest's CPUs", .user_print = monitor_user_noop, .mhandler.cmd_new = do_inject_nmi, }, #endif STEXI Loading
monitor.c +12 −7 Original line number Diff line number Diff line Loading @@ -2544,16 +2544,21 @@ static void do_wav_capture(Monitor *mon, const QDict *qdict) #endif #if defined(TARGET_I386) static void do_inject_nmi(Monitor *mon, const QDict *qdict) static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data) { CPUState *env; int cpu_index = qdict_get_int(qdict, "cpu_index"); for (env = first_cpu; env != NULL; env = env->next_cpu) if (env->cpu_index == cpu_index) { for (env = first_cpu; env != NULL; env = env->next_cpu) { cpu_interrupt(env, CPU_INTERRUPT_NMI); break; } return 0; } #else static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data) { qerror_report(QERR_UNSUPPORTED); return -1; } #endif Loading
qerror.c +4 −0 Original line number Diff line number Diff line Loading @@ -200,6 +200,10 @@ static const QErrorStringTable qerror_table[] = { .error_fmt = QERR_UNDEFINED_ERROR, .desc = "An undefined error has ocurred", }, { .error_fmt = QERR_UNSUPPORTED, .desc = "this feature or command is not currently supported", }, { .error_fmt = QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, .desc = "'%(device)' uses a %(format) feature which is not " Loading
qerror.h +3 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,9 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_UNDEFINED_ERROR \ "{ 'class': 'UndefinedError', 'data': {} }" #define QERR_UNSUPPORTED \ "{ 'class': 'Unsupported', 'data': {} }" #define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \ "{ 'class': 'UnknownBlockFormatFeature', 'data': { 'device': %s, 'format': %s, 'feature': %s } }" Loading