From 2c109f21994a72e9b91c24c422e540b921e84f66 Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:23 +0200 Subject: [PATCH 001/208] simpletrace: add __all__ to define public interface It was unclear what was the supported public interface. I.e. when refactoring the code, what functions/classes are important to retain. Reviewed-by: Stefan Hajnoczi Signed-off-by: Mads Ynddal Message-id: 20230926103436.25700-2-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- scripts/simpletrace.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 1f6d1ae1f3ec..b221d9a2415a 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -14,6 +14,8 @@ from tracetool import read_events, Event from tracetool.backend.simple import is_string +__all__ = ['Analyzer', 'process', 'run'] + header_event_id = 0xffffffffffffffff header_magic = 0xf2b177cb0aa429b4 dropped_event_id = 0xfffffffffffffffe From 8405ec6ab6a05b8c84f7be1130a7891d1a874624 Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:24 +0200 Subject: [PATCH 002/208] simpletrace: annotate magic constants from QEMU code It wasn't clear where the constants and structs came from, so I added comments to help. Reviewed-by: Stefan Hajnoczi Signed-off-by: Mads Ynddal Message-id: 20230926103436.25700-3-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- scripts/simpletrace.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index b221d9a2415a..5c230a1b74ca 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -16,6 +16,11 @@ __all__ = ['Analyzer', 'process', 'run'] +# This is the binary format that the QEMU "simple" trace backend +# emits. There is no specification documentation because the format is +# not guaranteed to be stable. Trace files must be parsed with the +# same trace-events-all file and the same simpletrace.py file that +# QEMU was built with. header_event_id = 0xffffffffffffffff header_magic = 0xf2b177cb0aa429b4 dropped_event_id = 0xfffffffffffffffe From f7bd4f0237ec394198940f5b81cbde280c5b5c01 Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:25 +0200 Subject: [PATCH 003/208] simpletrace: improve parsing of sys.argv; fix files never closed. The arguments extracted from `sys.argv` named and unpacked to make it clear what the arguments are and what they're used for. The two input files were opened, but never explicitly closed. File usage changed to use `with` statement to take care of this. At the same time, ownership of the file-object is moved up to `run` function. Added option to process to support file-like objects. Reviewed-by: Stefan Hajnoczi Signed-off-by: Mads Ynddal Message-id: 20230926103436.25700-4-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- scripts/simpletrace.py | 50 ++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 5c230a1b74ca..283b5918a1ac 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -9,6 +9,7 @@ # # For help see docs/devel/tracing.rst +import sys import struct import inspect from tracetool import read_events, Event @@ -51,7 +52,6 @@ def get_record(edict, idtoname, rechdr, fobj): try: event = edict[name] except KeyError as e: - import sys sys.stderr.write('%s event is logged but is not declared ' \ 'in the trace events file, try using ' \ 'trace-events-all instead.\n' % str(e)) @@ -172,11 +172,28 @@ def end(self): pass def process(events, log, analyzer, read_header=True): - """Invoke an analyzer on each event in a log.""" + """Invoke an analyzer on each event in a log. + Args: + events (file-object or list or str): events list or file-like object or file path as str to read event data from + log (file-object or str): file-like object or file path as str to read log data from + analyzer (Analyzer): Instance of Analyzer to interpret the event data + read_header (bool, optional): Whether to read header data from the log data. Defaults to True. + """ + if isinstance(events, str): - events = read_events(open(events, 'r'), events) + with open(events, 'r') as f: + events_list = read_events(f, events) + elif isinstance(events, list): + # Treat as a list of events already produced by tracetool.read_events + events_list = events + else: + # Treat as an already opened file-object + events_list = read_events(events, events.name) + + close_log = False if isinstance(log, str): log = open(log, 'rb') + close_log = True if read_header: read_trace_header(log) @@ -187,12 +204,12 @@ def process(events, log, analyzer, read_header=True): edict = {"dropped": dropped_event} idtoname = {dropped_event_id: "dropped"} - for event in events: + for event in events_list: edict[event.name] = event # If there is no header assume event ID mapping matches events list if not read_header: - for event_id, event in enumerate(events): + for event_id, event in enumerate(events_list): idtoname[event_id] = event.name def build_fn(analyzer, event): @@ -225,24 +242,25 @@ def build_fn(analyzer, event): fn_cache[event_num](event, rec) analyzer.end() + if close_log: + log.close() + def run(analyzer): """Execute an analyzer on a trace file given on the command-line. This function is useful as a driver for simple analysis scripts. More advanced scripts will want to call process() instead.""" - import sys - - read_header = True - if len(sys.argv) == 4 and sys.argv[1] == '--no-header': - read_header = False - del sys.argv[1] - elif len(sys.argv) != 3: - sys.stderr.write('usage: %s [--no-header] ' \ - '\n' % sys.argv[0]) + + try: + # NOTE: See built-in `argparse` module for a more robust cli interface + *no_header, trace_event_path, trace_file_path = sys.argv[1:] + assert no_header == [] or no_header == ['--no-header'], 'Invalid no-header argument' + except (AssertionError, ValueError): + sys.stderr.write(f'usage: {sys.argv[0]} [--no-header] \n') sys.exit(1) - events = read_events(open(sys.argv[1], 'r'), sys.argv[1]) - process(events, sys.argv[2], analyzer, read_header=read_header) + with open(trace_event_path, 'r') as events_fobj, open(trace_file_path, 'rb') as log_fobj: + process(events_fobj, log_fobj, analyzer, read_header=not no_header) if __name__ == '__main__': class Formatter(Analyzer): From 3b71b61e9f50cad73958a87216dba7b22b851318 Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:26 +0200 Subject: [PATCH 004/208] simpletrace: changed naming of edict and idtoname to improve readability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Readability is subjective, but I've expanded the naming of the variables and arguments, to help with understanding for new eyes on the code. Signed-off-by: Mads Ynddal Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Stefan Hajnoczi Message-id: 20230926103436.25700-5-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- scripts/simpletrace.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 283b5918a1ac..09511f624d17 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -40,17 +40,17 @@ def read_header(fobj, hfmt): return None return struct.unpack(hfmt, hdr) -def get_record(edict, idtoname, rechdr, fobj): +def get_record(event_mapping, event_id_to_name, rechdr, fobj): """Deserialize a trace record from a file into a tuple (name, timestamp, pid, arg1, ..., arg6).""" if rechdr is None: return None if rechdr[0] != dropped_event_id: event_id = rechdr[0] - name = idtoname[event_id] + name = event_id_to_name[event_id] rec = (name, rechdr[1], rechdr[3]) try: - event = edict[name] + event = event_mapping[name] except KeyError as e: sys.stderr.write('%s event is logged but is not declared ' \ 'in the trace events file, try using ' \ @@ -79,10 +79,10 @@ def get_mapping(fobj): return (event_id, name) -def read_record(edict, idtoname, fobj): +def read_record(event_mapping, event_id_to_name, fobj): """Deserialize a trace record from a file into a tuple (event_num, timestamp, pid, arg1, ..., arg6).""" rechdr = read_header(fobj, rec_header_fmt) - return get_record(edict, idtoname, rechdr, fobj) + return get_record(event_mapping, event_id_to_name, rechdr, fobj) def read_trace_header(fobj): """Read and verify trace file header""" @@ -103,14 +103,14 @@ def read_trace_header(fobj): raise ValueError('Log format %d not supported with this QEMU release!' % log_version) -def read_trace_records(edict, idtoname, fobj): +def read_trace_records(event_mapping, event_id_to_name, fobj): """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6). - Note that `idtoname` is modified if the file contains mapping records. + Note that `event_id_to_name` is modified if the file contains mapping records. Args: - edict (str -> Event): events dict, indexed by name - idtoname (int -> str): event names dict, indexed by event ID + event_mapping (str -> Event): events dict, indexed by name + event_id_to_name (int -> str): event names dict, indexed by event ID fobj (file): input file """ @@ -122,9 +122,9 @@ def read_trace_records(edict, idtoname, fobj): (rectype, ) = struct.unpack('=Q', t) if rectype == record_type_mapping: event_id, name = get_mapping(fobj) - idtoname[event_id] = name + event_id_to_name[event_id] = name else: - rec = read_record(edict, idtoname, fobj) + rec = read_record(event_mapping, event_id_to_name, fobj) yield rec @@ -201,16 +201,16 @@ def process(events, log, analyzer, read_header=True): frameinfo = inspect.getframeinfo(inspect.currentframe()) dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)", frameinfo.lineno + 1, frameinfo.filename) - edict = {"dropped": dropped_event} - idtoname = {dropped_event_id: "dropped"} + event_mapping = {"dropped": dropped_event} + event_id_to_name = {dropped_event_id: "dropped"} for event in events_list: - edict[event.name] = event + event_mapping[event.name] = event # If there is no header assume event ID mapping matches events list if not read_header: for event_id, event in enumerate(events_list): - idtoname[event_id] = event.name + event_id_to_name[event_id] = event.name def build_fn(analyzer, event): if isinstance(event, str): @@ -234,9 +234,9 @@ def build_fn(analyzer, event): analyzer.begin() fn_cache = {} - for rec in read_trace_records(edict, idtoname, log): + for rec in read_trace_records(event_mapping, event_id_to_name, log): event_num = rec[0] - event = edict[event_num] + event = event_mapping[event_num] if event_num not in fn_cache: fn_cache[event_num] = build_fn(analyzer, event) fn_cache[event_num](event, rec) From ce96eb334dc0a3a7f570f422e8a578495f34e4f2 Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:27 +0200 Subject: [PATCH 005/208] simpletrace: update code for Python 3.11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The call to `getargspec` was deprecated and in Python 3.11 it has been removed in favor of `getfullargspec`. `getfullargspec` is compatible with QEMU's requirement of at least Python version 3.6. Reviewed-by: Stefan Hajnoczi Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Mads Ynddal Message-id: 20230926103436.25700-6-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- scripts/simpletrace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 09511f624d17..971b2a0f6aff 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -221,7 +221,7 @@ def build_fn(analyzer, event): return analyzer.catchall event_argcount = len(event.args) - fn_argcount = len(inspect.getargspec(fn)[0]) - 1 + fn_argcount = len(inspect.getfullargspec(fn)[0]) - 1 if fn_argcount == event_argcount + 1: # Include timestamp as first argument return lambda _, rec: fn(*(rec[1:2] + rec[3:3 + event_argcount])) From d1f9259014317baa3bce7db7d4c2e927341e3cae Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:28 +0200 Subject: [PATCH 006/208] simpletrace: improved error handling on struct unpack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A failed call to `read_header` wouldn't be handled the same for the two different code paths (one path would try to use `None` as a list). Changed to raise exception to be handled centrally. This also allows for easier unpacking, as errors has been filtered out. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Stefan Hajnoczi Signed-off-by: Mads Ynddal Message-id: 20230926103436.25700-7-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- scripts/simpletrace.py | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 971b2a0f6aff..8aea0d169b14 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -37,26 +37,24 @@ def read_header(fobj, hfmt): hlen = struct.calcsize(hfmt) hdr = fobj.read(hlen) if len(hdr) != hlen: - return None + raise ValueError('Error reading header. Wrong filetype provided?') return struct.unpack(hfmt, hdr) def get_record(event_mapping, event_id_to_name, rechdr, fobj): """Deserialize a trace record from a file into a tuple (name, timestamp, pid, arg1, ..., arg6).""" - if rechdr is None: - return None - if rechdr[0] != dropped_event_id: - event_id = rechdr[0] + event_id, timestamp_ns, length, pid = rechdr + if event_id != dropped_event_id: name = event_id_to_name[event_id] - rec = (name, rechdr[1], rechdr[3]) try: event = event_mapping[name] except KeyError as e: - sys.stderr.write('%s event is logged but is not declared ' \ + sys.stderr.write(f'{e} event is logged but is not declared ' \ 'in the trace events file, try using ' \ - 'trace-events-all instead.\n' % str(e)) + 'trace-events-all instead.\n') sys.exit(1) + rec = (name, timestamp_ns, pid) for type, name in event.args: if is_string(type): l = fobj.read(4) @@ -67,9 +65,8 @@ def get_record(event_mapping, event_id_to_name, rechdr, fobj): (value,) = struct.unpack('=Q', fobj.read(8)) rec = rec + (value,) else: - rec = ("dropped", rechdr[1], rechdr[3]) - (value,) = struct.unpack('=Q', fobj.read(8)) - rec = rec + (value,) + (dropped_count,) = struct.unpack('=Q', fobj.read(8)) + rec = ("dropped", timestamp_ns, pid, dropped_count) return rec def get_mapping(fobj): @@ -86,22 +83,16 @@ def read_record(event_mapping, event_id_to_name, fobj): def read_trace_header(fobj): """Read and verify trace file header""" - header = read_header(fobj, log_header_fmt) - if header is None: - raise ValueError('Not a valid trace file!') - if header[0] != header_event_id: - raise ValueError('Not a valid trace file, header id %d != %d' % - (header[0], header_event_id)) - if header[1] != header_magic: - raise ValueError('Not a valid trace file, header magic %d != %d' % - (header[1], header_magic)) - - log_version = header[2] + _header_event_id, _header_magic, log_version = read_header(fobj, log_header_fmt) + if _header_event_id != header_event_id: + raise ValueError(f'Not a valid trace file, header id {_header_event_id} != {header_event_id}') + if _header_magic != header_magic: + raise ValueError(f'Not a valid trace file, header magic {_header_magic} != {header_magic}') + if log_version not in [0, 2, 3, 4]: - raise ValueError('Unknown version of tracelog format!') + raise ValueError(f'Unknown version {log_version} of tracelog format!') if log_version != 4: - raise ValueError('Log format %d not supported with this QEMU release!' - % log_version) + raise ValueError(f'Log format {log_version} not supported with this QEMU release!') def read_trace_records(event_mapping, event_id_to_name, fobj): """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6). From 1990fb98934d8e114ac73b0ca649bf4820ca896a Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:29 +0200 Subject: [PATCH 007/208] simpletrace: define exception and add handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define `SimpleException` to differentiate our exceptions from generic exceptions (IOError, etc.). Adapted simpletrace to support this and output to stderr. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Stefan Hajnoczi Signed-off-by: Mads Ynddal Message-id: 20230926103436.25700-8-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- scripts/simpletrace.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 8aea0d169b14..229b10aa990a 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -32,12 +32,15 @@ log_header_fmt = '=QQQ' rec_header_fmt = '=QQII' +class SimpleException(Exception): + pass + def read_header(fobj, hfmt): '''Read a trace record header''' hlen = struct.calcsize(hfmt) hdr = fobj.read(hlen) if len(hdr) != hlen: - raise ValueError('Error reading header. Wrong filetype provided?') + raise SimpleException('Error reading header. Wrong filetype provided?') return struct.unpack(hfmt, hdr) def get_record(event_mapping, event_id_to_name, rechdr, fobj): @@ -49,10 +52,10 @@ def get_record(event_mapping, event_id_to_name, rechdr, fobj): try: event = event_mapping[name] except KeyError as e: - sys.stderr.write(f'{e} event is logged but is not declared ' \ - 'in the trace events file, try using ' \ - 'trace-events-all instead.\n') - sys.exit(1) + raise SimpleException( + f'{e} event is logged but is not declared in the trace events' + 'file, try using trace-events-all instead.' + ) rec = (name, timestamp_ns, pid) for type, name in event.args: @@ -247,8 +250,7 @@ def run(analyzer): *no_header, trace_event_path, trace_file_path = sys.argv[1:] assert no_header == [] or no_header == ['--no-header'], 'Invalid no-header argument' except (AssertionError, ValueError): - sys.stderr.write(f'usage: {sys.argv[0]} [--no-header] \n') - sys.exit(1) + raise SimpleException(f'usage: {sys.argv[0]} [--no-header] \n') with open(trace_event_path, 'r') as events_fobj, open(trace_file_path, 'rb') as log_fobj: process(events_fobj, log_fobj, analyzer, read_header=not no_header) @@ -276,4 +278,8 @@ def catchall(self, event, rec): i += 1 print(' '.join(fields)) - run(Formatter()) + try: + run(Formatter()) + except SimpleException as e: + sys.stderr.write(str(e) + "\n") + sys.exit(1) From 87617b9ae63c4675460244d067e246b362dc3867 Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:30 +0200 Subject: [PATCH 008/208] simpletrace: made Analyzer into context-manager Instead of explicitly calling `begin` and `end`, we can change the class to use the context-manager paradigm. This is mostly a styling choice, used in modern Python code. But it also allows for more advanced analyzers to handle exceptions gracefully in the `__exit__` method (not demonstrated here). Reviewed-by: Stefan Hajnoczi Signed-off-by: Mads Ynddal Message-id: 20230926103436.25700-9-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- scripts/simpletrace.py | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 229b10aa990a..7f514d15773a 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -122,12 +122,13 @@ def read_trace_records(event_mapping, event_id_to_name, fobj): yield rec -class Analyzer(object): +class Analyzer: """A trace file analyzer which processes trace records. An analyzer can be passed to run() or process(). The begin() method is invoked, then each trace record is processed, and finally the end() method - is invoked. + is invoked. When Analyzer is used as a context-manager (using the `with` + statement), begin() and end() are called automatically. If a method matching a trace event name exists, it is invoked to process that trace record. Otherwise the catchall() method is invoked. @@ -165,6 +166,15 @@ def end(self): """Called at the end of the trace.""" pass + def __enter__(self): + self.begin() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if exc_type is None: + self.end() + return False + def process(events, log, analyzer, read_header=True): """Invoke an analyzer on each event in a log. Args: @@ -226,15 +236,14 @@ def build_fn(analyzer, event): # Just arguments, no timestamp or pid return lambda _, rec: fn(*rec[3:3 + event_argcount]) - analyzer.begin() - fn_cache = {} - for rec in read_trace_records(event_mapping, event_id_to_name, log): - event_num = rec[0] - event = event_mapping[event_num] - if event_num not in fn_cache: - fn_cache[event_num] = build_fn(analyzer, event) - fn_cache[event_num](event, rec) - analyzer.end() + with analyzer: + fn_cache = {} + for rec in read_trace_records(event_mapping, event_id_to_name, log): + event_num = rec[0] + event = event_mapping[event_num] + if event_num not in fn_cache: + fn_cache[event_num] = build_fn(analyzer, event) + fn_cache[event_num](event, rec) if close_log: log.close() From 6f53641a980df2d1b38503b10bfda9236fa075b4 Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:31 +0200 Subject: [PATCH 009/208] simpletrace: refactor to separate responsibilities Moved event_mapping and event_id_to_name down one level in the function call-stack to keep variable instantiation and usage closer (`process` and `run` has no use of the variables; `read_trace_records` does). Instead of passing event_mapping and event_id_to_name to the bottom of the call-stack, we move their use to `read_trace_records`. This separates responsibility and ownership of the information. `read_record` now just reads the arguments from the file-object by knowning the total number of bytes. Parsing it to specific arguments is moved up to `read_trace_records`. Special handling of dropped events removed, as they can be handled by the general code. Reviewed-by: Stefan Hajnoczi Signed-off-by: Mads Ynddal Message-id: 20230926103436.25700-10-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- scripts/simpletrace.py | 115 +++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 62 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 7f514d15773a..0826aef2830b 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -31,6 +31,7 @@ log_header_fmt = '=QQQ' rec_header_fmt = '=QQII' +rec_header_fmt_len = struct.calcsize(rec_header_fmt) class SimpleException(Exception): pass @@ -43,35 +44,6 @@ def read_header(fobj, hfmt): raise SimpleException('Error reading header. Wrong filetype provided?') return struct.unpack(hfmt, hdr) -def get_record(event_mapping, event_id_to_name, rechdr, fobj): - """Deserialize a trace record from a file into a tuple - (name, timestamp, pid, arg1, ..., arg6).""" - event_id, timestamp_ns, length, pid = rechdr - if event_id != dropped_event_id: - name = event_id_to_name[event_id] - try: - event = event_mapping[name] - except KeyError as e: - raise SimpleException( - f'{e} event is logged but is not declared in the trace events' - 'file, try using trace-events-all instead.' - ) - - rec = (name, timestamp_ns, pid) - for type, name in event.args: - if is_string(type): - l = fobj.read(4) - (len,) = struct.unpack('=L', l) - s = fobj.read(len) - rec = rec + (s,) - else: - (value,) = struct.unpack('=Q', fobj.read(8)) - rec = rec + (value,) - else: - (dropped_count,) = struct.unpack('=Q', fobj.read(8)) - rec = ("dropped", timestamp_ns, pid, dropped_count) - return rec - def get_mapping(fobj): (event_id, ) = struct.unpack('=Q', fobj.read(8)) (len, ) = struct.unpack('=L', fobj.read(4)) @@ -79,10 +51,11 @@ def get_mapping(fobj): return (event_id, name) -def read_record(event_mapping, event_id_to_name, fobj): - """Deserialize a trace record from a file into a tuple (event_num, timestamp, pid, arg1, ..., arg6).""" - rechdr = read_header(fobj, rec_header_fmt) - return get_record(event_mapping, event_id_to_name, rechdr, fobj) +def read_record(fobj): + """Deserialize a trace record from a file into a tuple (event_num, timestamp, pid, args).""" + event_id, timestamp_ns, record_length, record_pid = read_header(fobj, rec_header_fmt) + args_payload = fobj.read(record_length - rec_header_fmt_len) + return (event_id, timestamp_ns, record_pid, args_payload) def read_trace_header(fobj): """Read and verify trace file header""" @@ -97,17 +70,28 @@ def read_trace_header(fobj): if log_version != 4: raise ValueError(f'Log format {log_version} not supported with this QEMU release!') -def read_trace_records(event_mapping, event_id_to_name, fobj): - """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6). - - Note that `event_id_to_name` is modified if the file contains mapping records. +def read_trace_records(events, fobj, read_header): + """Deserialize trace records from a file, yielding record tuples (event, event_num, timestamp, pid, arg1, ..., arg6). Args: event_mapping (str -> Event): events dict, indexed by name - event_id_to_name (int -> str): event names dict, indexed by event ID fobj (file): input file + read_header (bool): whether headers were read from fobj """ + frameinfo = inspect.getframeinfo(inspect.currentframe()) + dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)", + frameinfo.lineno + 1, frameinfo.filename) + + event_mapping = {e.name: e for e in events} + event_mapping["dropped"] = dropped_event + event_id_to_name = {dropped_event_id: "dropped"} + + # If there is no header assume event ID mapping matches events list + if not read_header: + for event_id, event in enumerate(events): + event_id_to_name[event_id] = event.name + while True: t = fobj.read(8) if len(t) == 0: @@ -115,12 +99,35 @@ def read_trace_records(event_mapping, event_id_to_name, fobj): (rectype, ) = struct.unpack('=Q', t) if rectype == record_type_mapping: - event_id, name = get_mapping(fobj) - event_id_to_name[event_id] = name + event_id, event_name = get_mapping(fobj) + event_id_to_name[event_id] = event_name else: - rec = read_record(event_mapping, event_id_to_name, fobj) + event_id, timestamp_ns, pid, args_payload = read_record(fobj) + event_name = event_id_to_name[event_id] + + try: + event = event_mapping[event_name] + except KeyError as e: + raise SimpleException( + f'{e} event is logged but is not declared in the trace events' + 'file, try using trace-events-all instead.' + ) + + offset = 0 + args = [] + for type, _ in event.args: + if is_string(type): + (length,) = struct.unpack_from('=L', args_payload, offset=offset) + offset += 4 + s = args_payload[offset:offset+length] + offset += length + args.append(s) + else: + (value,) = struct.unpack_from('=Q', args_payload, offset=offset) + offset += 8 + args.append(value) - yield rec + yield (event_mapping[event_name], event_name, timestamp_ns, pid) + tuple(args) class Analyzer: """A trace file analyzer which processes trace records. @@ -202,20 +209,6 @@ def process(events, log, analyzer, read_header=True): if read_header: read_trace_header(log) - frameinfo = inspect.getframeinfo(inspect.currentframe()) - dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)", - frameinfo.lineno + 1, frameinfo.filename) - event_mapping = {"dropped": dropped_event} - event_id_to_name = {dropped_event_id: "dropped"} - - for event in events_list: - event_mapping[event.name] = event - - # If there is no header assume event ID mapping matches events list - if not read_header: - for event_id, event in enumerate(events_list): - event_id_to_name[event_id] = event.name - def build_fn(analyzer, event): if isinstance(event, str): return analyzer.catchall @@ -238,12 +231,10 @@ def build_fn(analyzer, event): with analyzer: fn_cache = {} - for rec in read_trace_records(event_mapping, event_id_to_name, log): - event_num = rec[0] - event = event_mapping[event_num] - if event_num not in fn_cache: - fn_cache[event_num] = build_fn(analyzer, event) - fn_cache[event_num](event, rec) + for event, event_id, timestamp_ns, record_pid, *rec_args in read_trace_records(events, log, read_header): + if event_id not in fn_cache: + fn_cache[event_id] = build_fn(analyzer, event) + fn_cache[event_id](event, (event_id, timestamp_ns, record_pid, *rec_args)) if close_log: log.close() From b78234e65cad8c4899a2cfcc5e5cd8d33fce1b95 Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:32 +0200 Subject: [PATCH 010/208] simpletrace: move logic of process into internal function To avoid duplicate code depending on input types and to better handle open/close of log with a context-manager, we move the logic of process into _process. Reviewed-by: Stefan Hajnoczi Signed-off-by: Mads Ynddal Message-id: 20230926103436.25700-11-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- scripts/simpletrace.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 0826aef2830b..6969fdd59a50 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -201,13 +201,26 @@ def process(events, log, analyzer, read_header=True): # Treat as an already opened file-object events_list = read_events(events, events.name) - close_log = False if isinstance(log, str): - log = open(log, 'rb') - close_log = True + with open(log, 'rb') as log_fobj: + _process(events_list, log_fobj, analyzer, read_header) + else: + # Treat `log` as an already opened file-object. We will not close it, + # as we do not own it. + _process(events_list, log, analyzer, read_header) + +def _process(events, log_fobj, analyzer, read_header=True): + """Internal function for processing + + Args: + events (list): list of events already produced by tracetool.read_events + log_fobj (file): file-object to read log data from + analyzer (Analyzer): the Analyzer to interpret the event data + read_header (bool, optional): Whether to read header data from the log data. Defaults to True. + """ if read_header: - read_trace_header(log) + read_trace_header(log_fobj) def build_fn(analyzer, event): if isinstance(event, str): @@ -231,14 +244,11 @@ def build_fn(analyzer, event): with analyzer: fn_cache = {} - for event, event_id, timestamp_ns, record_pid, *rec_args in read_trace_records(events, log, read_header): + for event, event_id, timestamp_ns, record_pid, *rec_args in read_trace_records(events, log_fobj, read_header): if event_id not in fn_cache: fn_cache[event_id] = build_fn(analyzer, event) fn_cache[event_id](event, (event_id, timestamp_ns, record_pid, *rec_args)) - if close_log: - log.close() - def run(analyzer): """Execute an analyzer on a trace file given on the command-line. From d1f89c23bd93e40e180d4fc727e691a698a6d522 Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:33 +0200 Subject: [PATCH 011/208] simpletrace: move event processing to Analyzer class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moved event processing to the Analyzer class to separate specific analyzer logic (like caching and function signatures) from the _process function. This allows for new types of Analyzer-based subclasses without changing the core code. Note, that the fn_cache is important for performance in cases where the analyzer is branching away from the catch-all a lot. The cache has no measurable performance penalty. Reviewed-by: Stefan Hajnoczi Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Mads Ynddal Message-id: 20230926103436.25700-12-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- scripts/simpletrace.py | 60 +++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 6969fdd59a50..4136d006001f 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -169,6 +169,35 @@ def catchall(self, event, rec): """Called if no specific method for processing a trace event has been found.""" pass + def _build_fn(self, event): + fn = getattr(self, event.name, None) + if fn is None: + # Return early to avoid costly call to inspect.getfullargspec + return self.catchall + + event_argcount = len(event.args) + fn_argcount = len(inspect.getfullargspec(fn)[0]) - 1 + if fn_argcount == event_argcount + 1: + # Include timestamp as first argument + return lambda _, rec: fn(*(rec[1:2] + rec[3:3 + event_argcount])) + elif fn_argcount == event_argcount + 2: + # Include timestamp and pid + return lambda _, rec: fn(*rec[1:3 + event_argcount]) + else: + # Just arguments, no timestamp or pid + return lambda _, rec: fn(*rec[3:3 + event_argcount]) + + def _process_event(self, rec_args, *, event, event_id, timestamp_ns, pid, **kwargs): + if not hasattr(self, '_fn_cache'): + # NOTE: Cannot depend on downstream subclasses to have + # super().__init__() because of legacy. + self._fn_cache = {} + + rec = (event_id, timestamp_ns, pid, *rec_args) + if event_id not in self._fn_cache: + self._fn_cache[event_id] = self._build_fn(event) + self._fn_cache[event_id](event, rec) + def end(self): """Called at the end of the trace.""" pass @@ -222,32 +251,15 @@ def _process(events, log_fobj, analyzer, read_header=True): if read_header: read_trace_header(log_fobj) - def build_fn(analyzer, event): - if isinstance(event, str): - return analyzer.catchall - - fn = getattr(analyzer, event.name, None) - if fn is None: - return analyzer.catchall - - event_argcount = len(event.args) - fn_argcount = len(inspect.getfullargspec(fn)[0]) - 1 - if fn_argcount == event_argcount + 1: - # Include timestamp as first argument - return lambda _, rec: fn(*(rec[1:2] + rec[3:3 + event_argcount])) - elif fn_argcount == event_argcount + 2: - # Include timestamp and pid - return lambda _, rec: fn(*rec[1:3 + event_argcount]) - else: - # Just arguments, no timestamp or pid - return lambda _, rec: fn(*rec[3:3 + event_argcount]) - with analyzer: - fn_cache = {} for event, event_id, timestamp_ns, record_pid, *rec_args in read_trace_records(events, log_fobj, read_header): - if event_id not in fn_cache: - fn_cache[event_id] = build_fn(analyzer, event) - fn_cache[event_id](event, (event_id, timestamp_ns, record_pid, *rec_args)) + analyzer._process_event( + rec_args, + event=event, + event_id=event_id, + timestamp_ns=timestamp_ns, + pid=record_pid, + ) def run(analyzer): """Execute an analyzer on a trace file given on the command-line. From 3470fef15a7bff730b00633346d28b889027a609 Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:34 +0200 Subject: [PATCH 012/208] simpletrace: added simplified Analyzer2 class By moving the dynamic argument construction to keyword-arguments, we can remove all of the specialized handling, and streamline it. If a tracing method wants to access these, they can define the kwargs, or ignore it be placing `**kwargs` at the end of the function's arguments list. Added deprecation warning to Analyzer class to make users aware of the Analyzer2 class. No removal date is planned. Signed-off-by: Mads Ynddal Message-id: 20230926103436.25700-13-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- scripts/simpletrace.py | 98 ++++++++++++++++++++++++++++++++---------- 1 file changed, 75 insertions(+), 23 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 4136d006001f..cef81b0707f0 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -12,10 +12,11 @@ import sys import struct import inspect +import warnings from tracetool import read_events, Event from tracetool.backend.simple import is_string -__all__ = ['Analyzer', 'process', 'run'] +__all__ = ['Analyzer', 'Analyzer2', 'process', 'run'] # This is the binary format that the QEMU "simple" trace backend # emits. There is no specification documentation because the format is @@ -130,7 +131,9 @@ def read_trace_records(events, fobj, read_header): yield (event_mapping[event_name], event_name, timestamp_ns, pid) + tuple(args) class Analyzer: - """A trace file analyzer which processes trace records. + """[Deprecated. Refer to Analyzer2 instead.] + + A trace file analyzer which processes trace records. An analyzer can be passed to run() or process(). The begin() method is invoked, then each trace record is processed, and finally the end() method @@ -188,6 +191,11 @@ def _build_fn(self, event): return lambda _, rec: fn(*rec[3:3 + event_argcount]) def _process_event(self, rec_args, *, event, event_id, timestamp_ns, pid, **kwargs): + warnings.warn( + "Use of deprecated Analyzer class. Refer to Analyzer2 instead.", + DeprecationWarning, + ) + if not hasattr(self, '_fn_cache'): # NOTE: Cannot depend on downstream subclasses to have # super().__init__() because of legacy. @@ -211,6 +219,56 @@ def __exit__(self, exc_type, exc_val, exc_tb): self.end() return False +class Analyzer2(Analyzer): + """A trace file analyzer which processes trace records. + + An analyzer can be passed to run() or process(). The begin() method is + invoked, then each trace record is processed, and finally the end() method + is invoked. When Analyzer is used as a context-manager (using the `with` + statement), begin() and end() are called automatically. + + If a method matching a trace event name exists, it is invoked to process + that trace record. Otherwise the catchall() method is invoked. + + The methods are called with a set of keyword-arguments. These can be ignored + using `**kwargs` or defined like any keyword-argument. + + The following keyword-arguments are available, but make sure to have an + **kwargs to allow for unmatched arguments in the future: + event: Event object of current trace + event_id: The id of the event in the current trace file + timestamp_ns: The timestamp in nanoseconds of the trace + pid: The process id recorded for the given trace + + Example: + The following method handles the runstate_set(int new_state) trace event:: + + def runstate_set(self, new_state, **kwargs): + ... + + The method can also explicitly take a timestamp keyword-argument with the + trace event arguments:: + + def runstate_set(self, new_state, *, timestamp_ns, **kwargs): + ... + + Timestamps have the uint64_t type and are in nanoseconds. + + The pid can be included in addition to the timestamp and is useful when + dealing with traces from multiple processes: + + def runstate_set(self, new_state, *, timestamp_ns, pid, **kwargs): + ... + """ + + def catchall(self, *rec_args, event, timestamp_ns, pid, event_id, **kwargs): + """Called if no specific method for processing a trace event has been found.""" + pass + + def _process_event(self, rec_args, *, event, **kwargs): + fn = getattr(self, event.name, self.catchall) + fn(*rec_args, event=event, **kwargs) + def process(events, log, analyzer, read_header=True): """Invoke an analyzer on each event in a log. Args: @@ -278,30 +336,24 @@ def run(analyzer): process(events_fobj, log_fobj, analyzer, read_header=not no_header) if __name__ == '__main__': - class Formatter(Analyzer): + class Formatter2(Analyzer2): def __init__(self): - self.last_timestamp = None - - def catchall(self, event, rec): - timestamp = rec[1] - if self.last_timestamp is None: - self.last_timestamp = timestamp - delta_ns = timestamp - self.last_timestamp - self.last_timestamp = timestamp - - fields = [event.name, '%0.3f' % (delta_ns / 1000.0), - 'pid=%d' % rec[2]] - i = 3 - for type, name in event.args: - if is_string(type): - fields.append('%s=%s' % (name, rec[i])) - else: - fields.append('%s=0x%x' % (name, rec[i])) - i += 1 - print(' '.join(fields)) + self.last_timestamp_ns = None + + def catchall(self, *rec_args, event, timestamp_ns, pid, event_id): + if self.last_timestamp_ns is None: + self.last_timestamp_ns = timestamp_ns + delta_ns = timestamp_ns - self.last_timestamp_ns + self.last_timestamp_ns = timestamp_ns + + fields = [ + f'{name}={r}' if is_string(type) else f'{name}=0x{r:x}' + for r, (type, name) in zip(rec_args, event.args) + ] + print(f'{event.name} {delta_ns / 1000:0.3f} {pid=} ' + ' '.join(fields)) try: - run(Formatter()) + run(Formatter2()) except SimpleException as e: sys.stderr.write(str(e) + "\n") sys.exit(1) From 84197267d1620405c664f6d4510288d0fd3a8837 Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:35 +0200 Subject: [PATCH 013/208] MAINTAINERS: add maintainer of simpletrace.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In my work to refactor simpletrace.py, I noticed that there's no maintainer of it, and has the status of "odd fixes". I'm using it from time to time, so I'd like to maintain the script. I've added myself as reviewer under "Tracing" to be informed of changes that might affect simpletrace.py. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Mads Ynddal Message-id: 20230926103436.25700-14-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 355b1960ce46..81625f036bdb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3170,6 +3170,7 @@ F: stubs/ Tracing M: Stefan Hajnoczi +R: Mads Ynddal S: Maintained F: trace/ F: trace-events @@ -3182,6 +3183,11 @@ F: docs/tools/qemu-trace-stap.rst F: docs/devel/tracing.rst T: git https://github.com/stefanha/qemu.git tracing +Simpletrace +M: Mads Ynddal +S: Maintained +F: scripts/simpletrace.py + TPM M: Stefan Berger S: Maintained From ff014701ab0f09fdbf37b4c39334790f9b298253 Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Tue, 26 Sep 2023 12:34:36 +0200 Subject: [PATCH 014/208] scripts/analyse-locks-simpletrace.py: changed iteritems() to items() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Python 3 removed `dict.iteritems()` in favor of `dict.items()`. This means the script currently doesn't work on Python 3. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Stefan Hajnoczi Signed-off-by: Mads Ynddal Message-id: 20230926103436.25700-15-mads@ynddal.dk Signed-off-by: Stefan Hajnoczi --- scripts/analyse-locks-simpletrace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/analyse-locks-simpletrace.py b/scripts/analyse-locks-simpletrace.py index 63c11f4fce20..d650dd714086 100755 --- a/scripts/analyse-locks-simpletrace.py +++ b/scripts/analyse-locks-simpletrace.py @@ -75,7 +75,7 @@ def get_args(): (analyser.locks, analyser.locked, analyser.unlocks)) # Now dump the individual lock stats - for key, val in sorted(analyser.mutex_records.iteritems(), + for key, val in sorted(analyser.mutex_records.items(), key=lambda k_v: k_v[1]["locks"]): print ("Lock: %#x locks: %d, locked: %d, unlocked: %d" % (key, val["locks"], val["locked"], val["unlocked"])) From d97fa9a00d5b333c8642670b7b55f9101d495dce Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Wed, 27 Sep 2023 11:10:00 +0200 Subject: [PATCH 015/208] tests/tcg/tricore: Bump cpu to tc37x we don't want to exclude ISA v1.6.2 insns from our tests. Acked-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-Id: <20230828112651.522058-2-kbastian@mail.uni-paderborn.de> --- tests/tcg/tricore/Makefile.softmmu-target | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tcg/tricore/Makefile.softmmu-target b/tests/tcg/tricore/Makefile.softmmu-target index 2ec0bd362257..d556201b07c6 100644 --- a/tests/tcg/tricore/Makefile.softmmu-target +++ b/tests/tcg/tricore/Makefile.softmmu-target @@ -25,7 +25,7 @@ TESTS += test_muls.asm.tst TESTS += test_boot_to_main.c.tst TESTS += test_context_save_areas.c.tst -QEMU_OPTS += -M tricore_testboard -cpu tc27x -nographic -kernel +QEMU_OPTS += -M tricore_testboard -cpu tc37x -nographic -kernel %.pS: $(ASM_TESTS_PATH)/%.S $(CC) -E -o $@ $< From 3e2a5107c52f5bf7ed68f4b468cff5be456f1097 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 28 Aug 2023 13:26:42 +0200 Subject: [PATCH 016/208] target/tricore: Implement CRCN insn reported in https://gitlab.com/qemu-project/qemu/-/issues/1667 Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-ID: <20230828112651.522058-3-kbastian@mail.uni-paderborn.de> --- target/tricore/helper.h | 1 + target/tricore/op_helper.c | 63 +++++++++++++++++++++++ target/tricore/translate.c | 8 +++ target/tricore/tricore-opcodes.h | 1 + tests/tcg/tricore/Makefile.softmmu-target | 1 + tests/tcg/tricore/asm/test_crcn.S | 9 ++++ 6 files changed, 83 insertions(+) create mode 100644 tests/tcg/tricore/asm/test_crcn.S diff --git a/target/tricore/helper.h b/target/tricore/helper.h index 31d71eac7a41..190645413a21 100644 --- a/target/tricore/helper.h +++ b/target/tricore/helper.h @@ -134,6 +134,7 @@ DEF_HELPER_FLAGS_5(mulr_h, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32, i32, i32) DEF_HELPER_FLAGS_2(crc32b, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(crc32_be, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(crc32_le, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_3(crcn, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_FLAGS_2(shuffle, TCG_CALL_NO_RWG_SE, i32, i32, i32) /* CSA */ DEF_HELPER_2(call, void, env, i32) diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c index 89be1ed648f8..0cf8eb50bdc6 100644 --- a/target/tricore/op_helper.c +++ b/target/tricore/op_helper.c @@ -2308,6 +2308,69 @@ uint32_t helper_crc32_le(uint32_t arg0, uint32_t arg1) return crc32(arg1, buf, 4); } +static uint32_t crc_div(uint32_t crc_in, uint32_t data, uint32_t gen, + uint32_t n, uint32_t m) +{ + uint32_t i; + + data = data << n; + for (i = 0; i < m; i++) { + if (crc_in & (1u << (n - 1))) { + crc_in <<= 1; + if (data & (1u << (m - 1))) { + crc_in++; + } + crc_in ^= gen; + } else { + crc_in <<= 1; + if (data & (1u << (m - 1))) { + crc_in++; + } + } + data <<= 1; + } + + return crc_in; +} + +uint32_t helper_crcn(uint32_t arg0, uint32_t arg1, uint32_t arg2) +{ + uint32_t crc_out, crc_in; + uint32_t n = extract32(arg0, 12, 4) + 1; + uint32_t gen = extract32(arg0, 16, n); + uint32_t inv = extract32(arg0, 9, 1); + uint32_t le = extract32(arg0, 8, 1); + uint32_t m = extract32(arg0, 0, 3) + 1; + uint32_t data = extract32(arg1, 0, m); + uint32_t seed = extract32(arg2, 0, n); + + if (le == 1) { + if (m == 0) { + data = 0; + } else { + data = revbit32(data) >> (32 - m); + } + } + + if (inv == 1) { + seed = ~seed; + } + + if (m > n) { + crc_in = (data >> (m - n)) ^ seed; + } else { + crc_in = (data << (n - m)) ^ seed; + } + + crc_out = crc_div(crc_in, data, gen, n, m); + + if (inv) { + crc_out = ~crc_out; + } + + return extract32(crc_out, 0, n); +} + uint32_t helper_shuffle(uint32_t arg0, uint32_t arg1) { uint32_t resb; diff --git a/target/tricore/translate.c b/target/tricore/translate.c index 6ae5ccbf726d..4e7e18f9855c 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -6669,6 +6669,14 @@ static void decode_rrr_divide(DisasContext *ctx) gen_helper_pack(cpu_gpr_d[r4], cpu_PSW_C, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]); break; + case OPC2_32_RRR_CRCN: + if (has_feature(ctx, TRICORE_FEATURE_162)) { + gen_helper_crcn(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r2], + cpu_gpr_d[r3]); + } else { + generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); + } + break; case OPC2_32_RRR_ADD_F: gen_helper_fadd(cpu_gpr_d[r4], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r3]); break; diff --git a/target/tricore/tricore-opcodes.h b/target/tricore/tricore-opcodes.h index bc62b731730a..f0705716657a 100644 --- a/target/tricore/tricore-opcodes.h +++ b/target/tricore/tricore-opcodes.h @@ -1247,6 +1247,7 @@ enum { OPC2_32_RRR_SUB_F = 0x03, OPC2_32_RRR_MADD_F = 0x06, OPC2_32_RRR_MSUB_F = 0x07, + OPC2_32_RRR_CRCN = 0x01, /* 1.6.2 up */ }; /* * RRR1 Format diff --git a/tests/tcg/tricore/Makefile.softmmu-target b/tests/tcg/tricore/Makefile.softmmu-target index d556201b07c6..b8d9b339337a 100644 --- a/tests/tcg/tricore/Makefile.softmmu-target +++ b/tests/tcg/tricore/Makefile.softmmu-target @@ -9,6 +9,7 @@ CFLAGS = -mtc162 -c -I$(TESTS_PATH) TESTS += test_abs.asm.tst TESTS += test_bmerge.asm.tst TESTS += test_clz.asm.tst +TESTS += test_crcn.asm.tst TESTS += test_dextr.asm.tst TESTS += test_dvstep.asm.tst TESTS += test_fadd.asm.tst diff --git a/tests/tcg/tricore/asm/test_crcn.S b/tests/tcg/tricore/asm/test_crcn.S new file mode 100644 index 000000000000..51a22722a3fa --- /dev/null +++ b/tests/tcg/tricore/asm/test_crcn.S @@ -0,0 +1,9 @@ +#include "macros.h" +.text +.global _start +_start: +# insn num result rs1 rs2 rs3 +# | | | | | | + TEST_D_DDD(crcn, 1, 0x00002bed, 0x0, 0xa10ddeed, 0x0) + + TEST_PASSFAIL From ce64babdf60fb9a7de8bcac637243a10db1a3b26 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 28 Aug 2023 13:26:43 +0200 Subject: [PATCH 017/208] target/tricore: Correctly handle FPU RM from PSW when we reconstructed PSW using psw_read(), we were trying to clear the cached USB bits out of env->PSW. The mask was wrong and we would clear PSW.RM as well. when we write the PSW using psw_write() we update the rounding modes in env->fp_status for softfloat. The order of bits used by TriCore is not the one used by softfloat. Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-ID: <20230828112651.522058-4-kbastian@mail.uni-paderborn.de> --- target/tricore/helper.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/target/tricore/helper.c b/target/tricore/helper.c index 6d076ac36fe7..e615c3d6d44c 100644 --- a/target/tricore/helper.c +++ b/target/tricore/helper.c @@ -120,7 +120,21 @@ void tricore_cpu_list(void) void fpu_set_state(CPUTriCoreState *env) { - set_float_rounding_mode(env->PSW & MASK_PSW_FPU_RM, &env->fp_status); + switch (extract32(env->PSW, 24, 2)) { + case 0: + set_float_rounding_mode(float_round_nearest_even, &env->fp_status); + break; + case 1: + set_float_rounding_mode(float_round_up, &env->fp_status); + break; + case 2: + set_float_rounding_mode(float_round_down, &env->fp_status); + break; + case 3: + set_float_rounding_mode(float_round_to_zero, &env->fp_status); + break; + } + set_flush_inputs_to_zero(1, &env->fp_status); set_flush_to_zero(1, &env->fp_status); set_default_nan_mode(1, &env->fp_status); @@ -129,7 +143,7 @@ void fpu_set_state(CPUTriCoreState *env) uint32_t psw_read(CPUTriCoreState *env) { /* clear all USB bits */ - env->PSW &= 0x6ffffff; + env->PSW &= 0x7ffffff; /* now set them from the cache */ env->PSW |= ((env->PSW_USB_C != 0) << 31); env->PSW |= ((env->PSW_USB_V & (1 << 31)) >> 1); From 2bdbe35632fc1f5f83054427085f59d28f45660f Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 28 Aug 2023 13:26:44 +0200 Subject: [PATCH 018/208] target/tricore: Implement FTOU insn Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-ID: <20230828112651.522058-5-kbastian@mail.uni-paderborn.de> --- target/tricore/fpu_helper.c | 32 +++++++++++++++++++++++ target/tricore/helper.h | 1 + target/tricore/translate.c | 3 +++ tests/tcg/tricore/Makefile.softmmu-target | 1 + tests/tcg/tricore/asm/test_ftou.S | 12 +++++++++ 5 files changed, 49 insertions(+) create mode 100644 tests/tcg/tricore/asm/test_ftou.S diff --git a/target/tricore/fpu_helper.c b/target/tricore/fpu_helper.c index cb7ee7dd35cb..3aefeb776eb3 100644 --- a/target/tricore/fpu_helper.c +++ b/target/tricore/fpu_helper.c @@ -429,6 +429,38 @@ uint32_t helper_ftoiz(CPUTriCoreState *env, uint32_t arg) return result; } +uint32_t helper_ftou(CPUTriCoreState *env, uint32_t arg) +{ + float32 f_arg = make_float32(arg); + uint32_t result; + int32_t flags = 0; + + result = float32_to_uint32(f_arg, &env->fp_status); + + flags = f_get_excp_flags(env); + if (flags & float_flag_invalid) { + flags &= ~float_flag_inexact; + if (float32_is_any_nan(f_arg)) { + result = 0; + } + /* + * we need to check arg < 0.0 before rounding as TriCore needs to raise + * float_flag_invalid as well. For instance, when we have a negative + * exponent and sign, softfloat would only raise float_flat_inexact. + */ + } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) { + flags = float_flag_invalid; + result = 0; + } + + if (flags) { + f_update_psw_flags(env, flags); + } else { + env->FPU_FS = 0; + } + return result; +} + uint32_t helper_ftouz(CPUTriCoreState *env, uint32_t arg) { float32 f_arg = make_float32(arg); diff --git a/target/tricore/helper.h b/target/tricore/helper.h index 190645413a21..827fbaa692e0 100644 --- a/target/tricore/helper.h +++ b/target/tricore/helper.h @@ -114,6 +114,7 @@ DEF_HELPER_2(ftoi, i32, env, i32) DEF_HELPER_2(itof, i32, env, i32) DEF_HELPER_2(utof, i32, env, i32) DEF_HELPER_2(ftoiz, i32, env, i32) +DEF_HELPER_2(ftou, i32, env, i32) DEF_HELPER_2(ftouz, i32, env, i32) DEF_HELPER_2(updfl, void, env, i32) /* dvinit */ diff --git a/target/tricore/translate.c b/target/tricore/translate.c index 4e7e18f9855c..382ecf4775d8 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -6269,6 +6269,9 @@ static void decode_rr_divide(DisasContext *ctx) case OPC2_32_RR_ITOF: gen_helper_itof(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); break; + case OPC2_32_RR_FTOU: + gen_helper_ftou(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + break; case OPC2_32_RR_FTOUZ: gen_helper_ftouz(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); break; diff --git a/tests/tcg/tricore/Makefile.softmmu-target b/tests/tcg/tricore/Makefile.softmmu-target index b8d9b339337a..91ae129a83d5 100644 --- a/tests/tcg/tricore/Makefile.softmmu-target +++ b/tests/tcg/tricore/Makefile.softmmu-target @@ -15,6 +15,7 @@ TESTS += test_dvstep.asm.tst TESTS += test_fadd.asm.tst TESTS += test_fmul.asm.tst TESTS += test_ftoi.asm.tst +TESTS += test_ftou.asm.tst TESTS += test_imask.asm.tst TESTS += test_insert.asm.tst TESTS += test_ld_bu.asm.tst diff --git a/tests/tcg/tricore/asm/test_ftou.S b/tests/tcg/tricore/asm/test_ftou.S new file mode 100644 index 000000000000..10f106ad6201 --- /dev/null +++ b/tests/tcg/tricore/asm/test_ftou.S @@ -0,0 +1,12 @@ +#include "macros.h" +.text +.global _start +_start: + TEST_D_D(ftou, 1, 0x00000000, 0x1733f6c2) + TEST_D_D(ftou, 2, 0x00000000, 0x2c9d9cdc) + TEST_D_D(ftou, 3, 0xffffffff, 0x56eb7395) + TEST_D_D(ftou, 4, 0x79900800, 0x4ef32010) + TEST_D_D(ftou, 5, 0x0353f510, 0x4c54fd44) + + TEST_PASSFAIL + From e43692bce684b76480df66473a9b3bec7a7d312a Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 28 Aug 2023 13:26:45 +0200 Subject: [PATCH 019/208] target/tricore: Clarify special case for FTOUZ insn this is not something other ISAs do, so clarify it with a comment. Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-ID: <20230828112651.522058-6-kbastian@mail.uni-paderborn.de> --- target/tricore/fpu_helper.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target/tricore/fpu_helper.c b/target/tricore/fpu_helper.c index 3aefeb776eb3..d0c474c5f3a9 100644 --- a/target/tricore/fpu_helper.c +++ b/target/tricore/fpu_helper.c @@ -475,6 +475,11 @@ uint32_t helper_ftouz(CPUTriCoreState *env, uint32_t arg) if (float32_is_any_nan(f_arg)) { result = 0; } + /* + * we need to check arg < 0.0 before rounding as TriCore needs to raise + * float_flag_invalid as well. For instance, when we have a negative + * exponent and sign, softfloat would only raise float_flat_inexact. + */ } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) { flags = float_flag_invalid; result = 0; From 815061b9da88a3a9a90fae58b5a778632e0cc2df Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 28 Aug 2023 13:26:46 +0200 Subject: [PATCH 020/208] target/tricore: Implement ftohp insn reported in https://gitlab.com/qemu-project/qemu/-/issues/1667 Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-ID: <20230828112651.522058-7-kbastian@mail.uni-paderborn.de> --- target/tricore/fpu_helper.c | 38 +++++++++++++++++++++++ target/tricore/helper.c | 1 + target/tricore/helper.h | 1 + target/tricore/translate.c | 7 +++++ target/tricore/tricore-opcodes.h | 1 + tests/tcg/tricore/Makefile.softmmu-target | 1 + tests/tcg/tricore/asm/test_ftohp.S | 14 +++++++++ 7 files changed, 63 insertions(+) create mode 100644 tests/tcg/tricore/asm/test_ftohp.S diff --git a/target/tricore/fpu_helper.c b/target/tricore/fpu_helper.c index d0c474c5f3a9..848c4a40a0c6 100644 --- a/target/tricore/fpu_helper.c +++ b/target/tricore/fpu_helper.c @@ -373,6 +373,44 @@ uint32_t helper_ftoi(CPUTriCoreState *env, uint32_t arg) return (uint32_t)result; } +uint32_t helper_ftohp(CPUTriCoreState *env, uint32_t arg) +{ + float32 f_arg = make_float32(arg); + uint32_t result = 0; + int32_t flags = 0; + + /* + * if we have any NAN we need to move the top 2 and lower 8 input mantissa + * bits to the top 2 and lower 8 output mantissa bits respectively. + * Softfloat on the other hand uses the top 10 mantissa bits. + */ + if (float32_is_any_nan(f_arg)) { + if (float32_is_signaling_nan(f_arg, &env->fp_status)) { + flags |= float_flag_invalid; + } + result = float16_set_sign(result, arg >> 31); + result = deposit32(result, 10, 5, 0x1f); + result = deposit32(result, 8, 2, extract32(arg, 21, 2)); + result = deposit32(result, 0, 8, extract32(arg, 0, 8)); + if (extract32(result, 0, 10) == 0) { + result |= (1 << 8); + } + } else { + set_flush_to_zero(0, &env->fp_status); + result = float32_to_float16(f_arg, true, &env->fp_status); + set_flush_to_zero(1, &env->fp_status); + flags = f_get_excp_flags(env); + } + + if (flags) { + f_update_psw_flags(env, flags); + } else { + env->FPU_FS = 0; + } + + return result; +} + uint32_t helper_itof(CPUTriCoreState *env, uint32_t arg) { float32 f_result; diff --git a/target/tricore/helper.c b/target/tricore/helper.c index e615c3d6d44c..7e5da3cb23ed 100644 --- a/target/tricore/helper.c +++ b/target/tricore/helper.c @@ -137,6 +137,7 @@ void fpu_set_state(CPUTriCoreState *env) set_flush_inputs_to_zero(1, &env->fp_status); set_flush_to_zero(1, &env->fp_status); + set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status); set_default_nan_mode(1, &env->fp_status); } diff --git a/target/tricore/helper.h b/target/tricore/helper.h index 827fbaa692e0..dcc5a492b3dd 100644 --- a/target/tricore/helper.h +++ b/target/tricore/helper.h @@ -111,6 +111,7 @@ DEF_HELPER_4(fmsub, i32, env, i32, i32, i32) DEF_HELPER_3(fcmp, i32, env, i32, i32) DEF_HELPER_2(qseed, i32, env, i32) DEF_HELPER_2(ftoi, i32, env, i32) +DEF_HELPER_2(ftohp, i32, env, i32) DEF_HELPER_2(itof, i32, env, i32) DEF_HELPER_2(utof, i32, env, i32) DEF_HELPER_2(ftoiz, i32, env, i32) diff --git a/target/tricore/translate.c b/target/tricore/translate.c index 382ecf4775d8..d76b6475f102 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -6260,6 +6260,13 @@ static void decode_rr_divide(DisasContext *ctx) case OPC2_32_RR_DIV_F: gen_helper_fdiv(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); break; + case OPC2_32_RR_FTOHP: + if (has_feature(ctx, TRICORE_FEATURE_162)) { + gen_helper_ftohp(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + } else { + generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); + } + break; case OPC2_32_RR_CMP_F: gen_helper_fcmp(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); break; diff --git a/target/tricore/tricore-opcodes.h b/target/tricore/tricore-opcodes.h index f0705716657a..29e655a6672a 100644 --- a/target/tricore/tricore-opcodes.h +++ b/target/tricore/tricore-opcodes.h @@ -1152,6 +1152,7 @@ enum { OPC2_32_RR_ITOF = 0x14, OPC2_32_RR_CMP_F = 0x00, OPC2_32_RR_FTOIZ = 0x13, + OPC2_32_RR_FTOHP = 0x25, /* 1.6.2 only */ OPC2_32_RR_FTOQ31 = 0x11, OPC2_32_RR_FTOQ31Z = 0x18, OPC2_32_RR_FTOU = 0x12, diff --git a/tests/tcg/tricore/Makefile.softmmu-target b/tests/tcg/tricore/Makefile.softmmu-target index 91ae129a83d5..fc545d45aec7 100644 --- a/tests/tcg/tricore/Makefile.softmmu-target +++ b/tests/tcg/tricore/Makefile.softmmu-target @@ -14,6 +14,7 @@ TESTS += test_dextr.asm.tst TESTS += test_dvstep.asm.tst TESTS += test_fadd.asm.tst TESTS += test_fmul.asm.tst +TESTS += test_ftohp.asm.tst TESTS += test_ftoi.asm.tst TESTS += test_ftou.asm.tst TESTS += test_imask.asm.tst diff --git a/tests/tcg/tricore/asm/test_ftohp.S b/tests/tcg/tricore/asm/test_ftohp.S new file mode 100644 index 000000000000..9e23141c1e09 --- /dev/null +++ b/tests/tcg/tricore/asm/test_ftohp.S @@ -0,0 +1,14 @@ +#include "macros.h" +.text +.global _start +_start: + TEST_D_D(ftohp, 1, 0xffff, 0xffffffff) + TEST_D_D(ftohp, 2, 0xfc00, 0xff800000) + TEST_D_D(ftohp, 3, 0x7c00, 0x7f800000) + TEST_D_D(ftohp, 4, 0x0, 0x0) + TEST_D_D(ftohp, 5, 0x5, 0x34a43580) + + #TEST_D_D_PSW(ftohp, 6, 0x400, 0x8c000b80, 0x387fee74) + + TEST_PASSFAIL + From 5e0e06d9a2ce13d5b9832f0dddeaf5e2f4f70591 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 28 Aug 2023 13:26:47 +0200 Subject: [PATCH 021/208] target/tricore: Implement hptof insn Reviewed-by: Richard Henderson Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1667 Signed-off-by: Bastian Koppelmann Message-ID: <20230828112651.522058-8-kbastian@mail.uni-paderborn.de> --- target/tricore/fpu_helper.c | 36 +++++++++++++++++++++++ target/tricore/helper.h | 1 + target/tricore/translate.c | 7 +++++ target/tricore/tricore-opcodes.h | 1 + tests/tcg/tricore/Makefile.softmmu-target | 1 + tests/tcg/tricore/asm/test_hptof.S | 12 ++++++++ 6 files changed, 58 insertions(+) create mode 100644 tests/tcg/tricore/asm/test_hptof.S diff --git a/target/tricore/fpu_helper.c b/target/tricore/fpu_helper.c index 848c4a40a0c6..5d38aea143af 100644 --- a/target/tricore/fpu_helper.c +++ b/target/tricore/fpu_helper.c @@ -373,6 +373,42 @@ uint32_t helper_ftoi(CPUTriCoreState *env, uint32_t arg) return (uint32_t)result; } +uint32_t helper_hptof(CPUTriCoreState *env, uint32_t arg) +{ + float16 f_arg = make_float16(arg); + uint32_t result = 0; + int32_t flags = 0; + + /* + * if we have any NAN we need to move the top 2 and lower 8 input mantissa + * bits to the top 2 and lower 8 output mantissa bits respectively. + * Softfloat on the other hand uses the top 10 mantissa bits. + */ + if (float16_is_any_nan(f_arg)) { + if (float16_is_signaling_nan(f_arg, &env->fp_status)) { + flags |= float_flag_invalid; + } + result = 0; + result = float32_set_sign(result, f_arg >> 15); + result = deposit32(result, 23, 8, 0xff); + result = deposit32(result, 21, 2, extract32(f_arg, 8, 2)); + result = deposit32(result, 0, 8, extract32(f_arg, 0, 8)); + } else { + set_flush_inputs_to_zero(0, &env->fp_status); + result = float16_to_float32(f_arg, true, &env->fp_status); + set_flush_inputs_to_zero(1, &env->fp_status); + flags = f_get_excp_flags(env); + } + + if (flags) { + f_update_psw_flags(env, flags); + } else { + env->FPU_FS = 0; + } + + return result; +} + uint32_t helper_ftohp(CPUTriCoreState *env, uint32_t arg) { float32 f_arg = make_float32(arg); diff --git a/target/tricore/helper.h b/target/tricore/helper.h index dcc5a492b3dd..1d97d078b002 100644 --- a/target/tricore/helper.h +++ b/target/tricore/helper.h @@ -112,6 +112,7 @@ DEF_HELPER_3(fcmp, i32, env, i32, i32) DEF_HELPER_2(qseed, i32, env, i32) DEF_HELPER_2(ftoi, i32, env, i32) DEF_HELPER_2(ftohp, i32, env, i32) +DEF_HELPER_2(hptof, i32, env, i32) DEF_HELPER_2(itof, i32, env, i32) DEF_HELPER_2(utof, i32, env, i32) DEF_HELPER_2(ftoiz, i32, env, i32) diff --git a/target/tricore/translate.c b/target/tricore/translate.c index d76b6475f102..c9823ee32a55 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -6267,6 +6267,13 @@ static void decode_rr_divide(DisasContext *ctx) generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); } break; + case OPC2_32_RR_HPTOF: + if (has_feature(ctx, TRICORE_FEATURE_162)) { + gen_helper_hptof(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + } else { + generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); + } + break; case OPC2_32_RR_CMP_F: gen_helper_fcmp(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); break; diff --git a/target/tricore/tricore-opcodes.h b/target/tricore/tricore-opcodes.h index 29e655a6672a..60d2402b6e39 100644 --- a/target/tricore/tricore-opcodes.h +++ b/target/tricore/tricore-opcodes.h @@ -1153,6 +1153,7 @@ enum { OPC2_32_RR_CMP_F = 0x00, OPC2_32_RR_FTOIZ = 0x13, OPC2_32_RR_FTOHP = 0x25, /* 1.6.2 only */ + OPC2_32_RR_HPTOF = 0x24, /* 1.6.2 only */ OPC2_32_RR_FTOQ31 = 0x11, OPC2_32_RR_FTOQ31Z = 0x18, OPC2_32_RR_FTOU = 0x12, diff --git a/tests/tcg/tricore/Makefile.softmmu-target b/tests/tcg/tricore/Makefile.softmmu-target index fc545d45aec7..258aeb40ae84 100644 --- a/tests/tcg/tricore/Makefile.softmmu-target +++ b/tests/tcg/tricore/Makefile.softmmu-target @@ -17,6 +17,7 @@ TESTS += test_fmul.asm.tst TESTS += test_ftohp.asm.tst TESTS += test_ftoi.asm.tst TESTS += test_ftou.asm.tst +TESTS += test_hptof.asm.tst TESTS += test_imask.asm.tst TESTS += test_insert.asm.tst TESTS += test_ld_bu.asm.tst diff --git a/tests/tcg/tricore/asm/test_hptof.S b/tests/tcg/tricore/asm/test_hptof.S new file mode 100644 index 000000000000..8adc5e5273f6 --- /dev/null +++ b/tests/tcg/tricore/asm/test_hptof.S @@ -0,0 +1,12 @@ +#include "macros.h" +.text +.global _start +_start: + TEST_D_D(hptof, 1, 0xba190000, 0xcc0e90c8) + TEST_D_D(hptof, 2, 0x3eaea000, 0x8be23575) + TEST_D_D(hptof, 3, 0xc33b8000, 0xcc48d9dc) + TEST_D_D(hptof, 4, 0x43e2a000, 0xaef95f15) + TEST_D_D(hptof, 5, 0x3d55e000, 0x04932aaf) + + TEST_PASSFAIL + From 23fa6f56b33f8fddf86ba4d027fb7d3081440cd9 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 28 Aug 2023 13:26:48 +0200 Subject: [PATCH 022/208] target/tricore: Fix RCPW/RRPW_INSERT insns for width = 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit we would crash if width was 0 for these insns, as tcg_gen_deposit() is undefined for that case. For TriCore, width = 0 is a mov from the src reg to the dst reg, so we special case this here. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-ID: <20230828112651.522058-9-kbastian@mail.uni-paderborn.de> --- target/tricore/translate.c | 10 ++++++++-- tests/tcg/tricore/asm/macros.h | 15 +++++++++++++++ tests/tcg/tricore/asm/test_insert.S | 9 +++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/target/tricore/translate.c b/target/tricore/translate.c index c9823ee32a55..3f950ae33b94 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -5310,8 +5310,11 @@ static void decode_rcpw_insert(DisasContext *ctx) } break; case OPC2_32_RCPW_INSERT: + /* tcg_gen_deposit_tl() does not handle the case of width = 0 */ + if (width == 0) { + tcg_gen_mov_tl(cpu_gpr_d[r2], cpu_gpr_d[r1]); /* if pos + width > 32 undefined result */ - if (pos + width <= 32) { + } else if (pos + width <= 32) { temp = tcg_constant_i32(const4); tcg_gen_deposit_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], temp, pos, width); } @@ -6571,7 +6574,10 @@ static void decode_rrpw_extract_insert(DisasContext *ctx) break; case OPC2_32_RRPW_INSERT: - if (pos + width <= 32) { + /* tcg_gen_deposit_tl() does not handle the case of width = 0 */ + if (width == 0) { + tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]); + } else if (pos + width <= 32) { tcg_gen_deposit_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], pos, width); } diff --git a/tests/tcg/tricore/asm/macros.h b/tests/tcg/tricore/asm/macros.h index b5087b5c97e5..51f6191ef2f7 100644 --- a/tests/tcg/tricore/asm/macros.h +++ b/tests/tcg/tricore/asm/macros.h @@ -161,6 +161,21 @@ test_ ## num: \ insn DREG_CALC_RESULT, DREG_RS1, imm1, DREG_RS2, imm2; \ ) +#define TEST_D_DDII(insn, num, result, rs1, rs2, imm1, imm2) \ + TEST_CASE(num, DREG_CALC_RESULT, result, \ + LI(DREG_RS1, rs1); \ + LI(DREG_RS2, rs2); \ + rstv; \ + insn DREG_CALC_RESULT, DREG_RS1, DREG_RS2, imm1, imm2; \ + ) + +#define TEST_D_DIII(insn, num, result, rs1, imm1, imm2, imm3)\ + TEST_CASE(num, DREG_CALC_RESULT, result, \ + LI(DREG_RS1, rs1); \ + rstv; \ + insn DREG_CALC_RESULT, DREG_RS1, imm1, imm2, imm3; \ + ) + #define TEST_E_ED(insn, num, res_hi, res_lo, rs1_hi, rs1_lo, rs2) \ TEST_CASE_E(num, res_lo, res_hi, \ LI(EREG_RS1_LO, rs1_lo); \ diff --git a/tests/tcg/tricore/asm/test_insert.S b/tests/tcg/tricore/asm/test_insert.S index d5fd2237e188..397881012144 100644 --- a/tests/tcg/tricore/asm/test_insert.S +++ b/tests/tcg/tricore/asm/test_insert.S @@ -6,4 +6,13 @@ _start: # | | | | | | | TEST_D_DIDI(insert, 1, 0x7fffffff, 0xffffffff, 0xa, 0x10, 0x8) +# insn num result rs1 imm1 imm2 imm3 +# | | | | | | | + TEST_D_DIII(insert, 2, 0xd38fe370, 0xd38fe370, 0x4, 0x4 , 0x0) + TEST_D_DIII(insert, 3, 0xd38fe374, 0xd38fe370, 0x4, 0x0 , 0x4) + +# insn num result rs1 rs2 pos width +# | | | | | | | + TEST_D_DDII(insert, 4, 0x03c1e53c, 0x03c1e53c, 0x45821385, 0x7 ,0x0) + TEST_PASSFAIL From 222ff2d3581e46731fe19644dfc4c4f36f39ac03 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 28 Aug 2023 13:26:49 +0200 Subject: [PATCH 023/208] target/tricore: Swap src and dst reg for RCRR_INSERT Acked-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-ID: <20230828112651.522058-10-kbastian@mail.uni-paderborn.de> --- target/tricore/translate.c | 8 ++++---- tests/tcg/tricore/asm/macros.h | 9 +++++++++ tests/tcg/tricore/asm/test_insert.S | 5 +++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/target/tricore/translate.c b/target/tricore/translate.c index 3f950ae33b94..7aba7b067c33 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -8223,12 +8223,12 @@ static void decode_32Bit_opc(DisasContext *ctx) temp2 = tcg_temp_new(); /* width*/ temp3 = tcg_temp_new(); /* pos */ - CHECK_REG_PAIR(r3); + CHECK_REG_PAIR(r2); - tcg_gen_andi_tl(temp2, cpu_gpr_d[r3+1], 0x1f); - tcg_gen_andi_tl(temp3, cpu_gpr_d[r3], 0x1f); + tcg_gen_andi_tl(temp2, cpu_gpr_d[r2 + 1], 0x1f); + tcg_gen_andi_tl(temp3, cpu_gpr_d[r2], 0x1f); - gen_insert(cpu_gpr_d[r2], cpu_gpr_d[r1], temp, temp2, temp3); + gen_insert(cpu_gpr_d[r3], cpu_gpr_d[r1], temp, temp2, temp3); break; /* RCRW Format */ case OPCM_32_RCRW_MASK_INSERT: diff --git a/tests/tcg/tricore/asm/macros.h b/tests/tcg/tricore/asm/macros.h index 51f6191ef2f7..17e696bef588 100644 --- a/tests/tcg/tricore/asm/macros.h +++ b/tests/tcg/tricore/asm/macros.h @@ -169,6 +169,15 @@ test_ ## num: \ insn DREG_CALC_RESULT, DREG_RS1, DREG_RS2, imm1, imm2; \ ) +#define TEST_D_DIE(insn, num, result, rs1, imm1, rs2_lo, rs2_hi)\ + TEST_CASE(num, DREG_CALC_RESULT, result, \ + LI(DREG_RS1, rs1); \ + LI(EREG_RS2_LO, rs2_lo); \ + LI(EREG_RS2_HI, rs2_hi); \ + rstv; \ + insn DREG_CALC_RESULT, DREG_RS1, imm1, EREG_RS2; \ + ) + #define TEST_D_DIII(insn, num, result, rs1, imm1, imm2, imm3)\ TEST_CASE(num, DREG_CALC_RESULT, result, \ LI(DREG_RS1, rs1); \ diff --git a/tests/tcg/tricore/asm/test_insert.S b/tests/tcg/tricore/asm/test_insert.S index 397881012144..223d7ce796c8 100644 --- a/tests/tcg/tricore/asm/test_insert.S +++ b/tests/tcg/tricore/asm/test_insert.S @@ -15,4 +15,9 @@ _start: # | | | | | | | TEST_D_DDII(insert, 4, 0x03c1e53c, 0x03c1e53c, 0x45821385, 0x7 ,0x0) +# insn num result rs1 imm1 rs2_h rs2_l +# | | | | | | | + TEST_D_DIE(insert, 5, 0xe30c308d, 0xe30c308d ,0x3 , 0x00000000 ,0x00000000) + TEST_D_DIE(insert, 6, 0x669b0120, 0x669b2820 ,0x2 , 0x5530a1c7 ,0x3a2b0f67) + TEST_PASSFAIL From 1f22db19533c6e8b01274d12c161c063083e2fba Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 28 Aug 2023 13:26:50 +0200 Subject: [PATCH 024/208] target/tricore: Replace cpu_*_code with translator_* Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-ID: <20230828112651.522058-11-kbastian@mail.uni-paderborn.de> --- target/tricore/translate.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/target/tricore/translate.c b/target/tricore/translate.c index 7aba7b067c33..2107d1fdd4c7 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -8398,7 +8398,7 @@ static bool insn_crosses_page(CPUTriCoreState *env, DisasContext *ctx) * 4 bytes from the page boundary, so we cross the page if the first * 16 bits indicate that this is a 32 bit insn. */ - uint16_t insn = cpu_lduw_code(env, ctx->base.pc_next); + uint16_t insn = translator_lduw(env, &ctx->base, ctx->base.pc_next); return !tricore_insn_is_16bit(insn); } @@ -8411,14 +8411,15 @@ static void tricore_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) uint16_t insn_lo; bool is_16bit; - insn_lo = cpu_lduw_code(env, ctx->base.pc_next); + insn_lo = translator_lduw(env, &ctx->base, ctx->base.pc_next); is_16bit = tricore_insn_is_16bit(insn_lo); if (is_16bit) { ctx->opcode = insn_lo; ctx->pc_succ_insn = ctx->base.pc_next + 2; decode_16Bit_opc(ctx); } else { - uint32_t insn_hi = cpu_lduw_code(env, ctx->base.pc_next + 2); + uint32_t insn_hi = translator_lduw(env, &ctx->base, + ctx->base.pc_next + 2); ctx->opcode = insn_hi << 16 | insn_lo; ctx->pc_succ_insn = ctx->base.pc_next + 4; decode_32Bit_opc(ctx); From 4f79db4750cbabed18f11cd791c5e5222a711fd5 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 28 Aug 2023 13:26:51 +0200 Subject: [PATCH 025/208] target/tricore: Fix FTOUZ being ISA v1.3.1 up Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Message-ID: <20230828112651.522058-12-kbastian@mail.uni-paderborn.de> --- target/tricore/translate.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/target/tricore/translate.c b/target/tricore/translate.c index 2107d1fdd4c7..7b53307effc1 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -6290,7 +6290,11 @@ static void decode_rr_divide(DisasContext *ctx) gen_helper_ftou(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); break; case OPC2_32_RR_FTOUZ: - gen_helper_ftouz(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + if (has_feature(ctx, TRICORE_FEATURE_131)) { + gen_helper_ftouz(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + } else { + generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); + } break; case OPC2_32_RR_UPDFL: gen_helper_updfl(cpu_env, cpu_gpr_d[r1]); From 8c3cf3f2bdf072b5ead13db81f1e6d879cd09bb6 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Wed, 13 Sep 2023 12:53:17 +0200 Subject: [PATCH 026/208] tests/tcg/tricore: Extended and non-extened regs now match RSx for d regs and e regs now use the same numbering. This makes sure that mixing d and e registers in an insn test will not overwrite data between registers. Signed-off-by: Bastian Koppelmann Message-ID: <20230913105326.40832-2-kbastian@mail.uni-paderborn.de> --- tests/tcg/tricore/asm/macros.h | 38 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/tcg/tricore/asm/macros.h b/tests/tcg/tricore/asm/macros.h index 17e696bef588..0f349dbf1e17 100644 --- a/tests/tcg/tricore/asm/macros.h +++ b/tests/tcg/tricore/asm/macros.h @@ -12,31 +12,31 @@ #define TESTDEV_ADDR 0xf0000000 /* Register definitions */ #define DREG_RS1 %d0 -#define DREG_RS2 %d1 -#define DREG_RS3 %d2 -#define DREG_CALC_RESULT %d3 -#define DREG_CALC_PSW %d4 -#define DREG_CORRECT_PSW %d5 -#define DREG_TEMP_LI %d10 -#define DREG_TEMP %d11 -#define DREG_TEST_NUM %d14 -#define DREG_CORRECT_RESULT %d15 -#define DREG_CORRECT_RESULT_2 %d13 +#define DREG_RS2 %d2 +#define DREG_RS3 %d4 +#define DREG_CALC_RESULT %d5 +#define DREG_CALC_PSW %d6 +#define DREG_CORRECT_PSW %d7 +#define DREG_TEMP_LI %d13 +#define DREG_TEMP %d14 +#define DREG_TEST_NUM %d8 +#define DREG_CORRECT_RESULT %d9 +#define DREG_CORRECT_RESULT_2 %d10 #define AREG_ADDR %a0 #define AREG_CORRECT_RESULT %a3 #define DREG_DEV_ADDR %a15 -#define EREG_RS1 %e6 -#define EREG_RS1_LO %d6 -#define EREG_RS1_HI %d7 -#define EREG_RS2 %e8 -#define EREG_RS2_LO %d8 -#define EREG_RS2_HI %d9 -#define EREG_CALC_RESULT %e8 -#define EREG_CALC_RESULT_HI %d9 -#define EREG_CALC_RESULT_LO %d8 +#define EREG_RS1 %e0 +#define EREG_RS1_LO %d0 +#define EREG_RS1_HI %d1 +#define EREG_RS2 %e2 +#define EREG_RS2_LO %d2 +#define EREG_RS2_HI %d3 +#define EREG_CALC_RESULT %e6 +#define EREG_CALC_RESULT_LO %d6 +#define EREG_CALC_RESULT_HI %d7 #define EREG_CORRECT_RESULT_LO %d0 #define EREG_CORRECT_RESULT_HI %d1 From f47a90dacca8f74210a2675bdde7ab3856872b94 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 14 Sep 2023 07:39:07 -0700 Subject: [PATCH 027/208] accel/tcg: Avoid load of icount_decr if unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With CF_NOIRQ and without !CF_USE_ICOUNT, the load isn't used. Avoid emitting it. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- accel/tcg/translator.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 1a6a5448c8fb..a3983019a528 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -49,12 +49,15 @@ bool translator_io_start(DisasContextBase *db) static TCGOp *gen_tb_start(uint32_t cflags) { - TCGv_i32 count = tcg_temp_new_i32(); + TCGv_i32 count = NULL; TCGOp *icount_start_insn = NULL; - tcg_gen_ld_i32(count, cpu_env, - offsetof(ArchCPU, neg.icount_decr.u32) - - offsetof(ArchCPU, env)); + if ((cflags & CF_USE_ICOUNT) || !(cflags & CF_NOIRQ)) { + count = tcg_temp_new_i32(); + tcg_gen_ld_i32(count, cpu_env, + offsetof(ArchCPU, neg.icount_decr.u32) - + offsetof(ArchCPU, env)); + } if (cflags & CF_USE_ICOUNT) { /* From 5d97e94638100fd3e5b8d76ab30e1066cd4b1823 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 14 Sep 2023 07:48:39 -0700 Subject: [PATCH 028/208] accel/tcg: Hoist CF_MEMI_ONLY check outside translation loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The condition checked is loop invariant; check it only once. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- accel/tcg/translator.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index a3983019a528..b6ab9f3d33ec 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -158,7 +158,13 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, ops->tb_start(db, cpu); tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ - plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY); + if (cflags & CF_MEMI_ONLY) { + /* We should only see CF_MEMI_ONLY for io_recompile. */ + assert(cflags & CF_LAST_IO); + plugin_enabled = plugin_gen_tb_start(cpu, db, true); + } else { + plugin_enabled = plugin_gen_tb_start(cpu, db, false); + } while (true) { *max_insns = ++db->num_insns; @@ -176,12 +182,8 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) { /* Accept I/O on the last instruction. */ gen_io_start(); - ops->translate_insn(db, cpu); - } else { - /* we should only see CF_MEMI_ONLY for io_recompile */ - tcg_debug_assert(!(cflags & CF_MEMI_ONLY)); - ops->translate_insn(db, cpu); } + ops->translate_insn(db, cpu); /* * We can't instrument after instructions that change control From 0ca41ccf1c555f97873b8e02a47390fd6af4b18f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 14 Sep 2023 08:06:14 -0700 Subject: [PATCH 029/208] accel/tcg: Track current value of can_do_io in the TB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify translator_io_start by recording the current known value of can_do_io within DisasContextBase. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- accel/tcg/translator.c | 31 ++++++++++++++----------------- include/exec/translator.h | 2 ++ 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index b6ab9f3d33ec..850d82e26f9c 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -16,11 +16,14 @@ #include "tcg/tcg-op-common.h" #include "internal.h" -static void gen_io_start(void) +static void set_can_do_io(DisasContextBase *db, bool val) { - tcg_gen_st_i32(tcg_constant_i32(1), cpu_env, - offsetof(ArchCPU, parent_obj.can_do_io) - - offsetof(ArchCPU, env)); + if (db->saved_can_do_io != val) { + db->saved_can_do_io = val; + tcg_gen_st_i32(tcg_constant_i32(val), cpu_env, + offsetof(ArchCPU, parent_obj.can_do_io) - + offsetof(ArchCPU, env)); + } } bool translator_io_start(DisasContextBase *db) @@ -30,12 +33,8 @@ bool translator_io_start(DisasContextBase *db) if (!(cflags & CF_USE_ICOUNT)) { return false; } - if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) { - /* Already started in translator_loop. */ - return true; - } - gen_io_start(); + set_can_do_io(db, true); /* * Ensure that this instruction will be the last in the TB. @@ -47,7 +46,7 @@ bool translator_io_start(DisasContextBase *db) return true; } -static TCGOp *gen_tb_start(uint32_t cflags) +static TCGOp *gen_tb_start(DisasContextBase *db, uint32_t cflags) { TCGv_i32 count = NULL; TCGOp *icount_start_insn = NULL; @@ -91,12 +90,9 @@ static TCGOp *gen_tb_start(uint32_t cflags) * cpu->can_do_io is cleared automatically here at the beginning of * each translation block. The cost is minimal and only paid for * -icount, plus it would be very easy to forget doing it in the - * translator. Doing it here means we don't need a gen_io_end() to - * go with gen_io_start(). + * translator. */ - tcg_gen_st_i32(tcg_constant_i32(0), cpu_env, - offsetof(ArchCPU, parent_obj.can_do_io) - - offsetof(ArchCPU, env)); + set_can_do_io(db, false); } return icount_start_insn; @@ -147,6 +143,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, db->num_insns = 0; db->max_insns = *max_insns; db->singlestep_enabled = cflags & CF_SINGLE_STEP; + db->saved_can_do_io = -1; db->host_addr[0] = host_pc; db->host_addr[1] = NULL; @@ -154,7 +151,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ /* Start translating. */ - icount_start_insn = gen_tb_start(cflags); + icount_start_insn = gen_tb_start(db, cflags); ops->tb_start(db, cpu); tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ @@ -181,7 +178,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, the next instruction. */ if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) { /* Accept I/O on the last instruction. */ - gen_io_start(); + set_can_do_io(db, true); } ops->translate_insn(db, cpu); diff --git a/include/exec/translator.h b/include/exec/translator.h index 4e17c4f401d6..9d9e980819c4 100644 --- a/include/exec/translator.h +++ b/include/exec/translator.h @@ -72,6 +72,7 @@ typedef enum DisasJumpType { * @num_insns: Number of translated instructions (including current). * @max_insns: Maximum number of instructions to be translated in this TB. * @singlestep_enabled: "Hardware" single stepping enabled. + * @saved_can_do_io: Known value of cpu->neg.can_do_io, or -1 for unknown. * * Architecture-agnostic disassembly context. */ @@ -83,6 +84,7 @@ typedef struct DisasContextBase { int num_insns; int max_insns; bool singlestep_enabled; + int8_t saved_can_do_io; void *host_addr[2]; } DisasContextBase; From a2f99d484c54adda13e62bf75ba512618a3fe470 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 14 Sep 2023 08:26:47 -0700 Subject: [PATCH 030/208] accel/tcg: Improve setting of can_do_io at start of TB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initialize can_do_io to true if this the TB has CF_LAST_IO and will consist of a single instruction. This avoids a set to 0 followed immediately by a set to 1. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- accel/tcg/translator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 850d82e26f9c..dd507cd4719a 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -87,12 +87,12 @@ static TCGOp *gen_tb_start(DisasContextBase *db, uint32_t cflags) offsetof(ArchCPU, neg.icount_decr.u16.low) - offsetof(ArchCPU, env)); /* - * cpu->can_do_io is cleared automatically here at the beginning of + * cpu->can_do_io is set automatically here at the beginning of * each translation block. The cost is minimal and only paid for * -icount, plus it would be very easy to forget doing it in the * translator. */ - set_can_do_io(db, false); + set_can_do_io(db, db->max_insns == 1 && (cflags & CF_LAST_IO)); } return icount_start_insn; From 200c1f904f46c209cb022e711a48b89e46512902 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 14 Sep 2023 08:36:11 -0700 Subject: [PATCH 031/208] accel/tcg: Always set CF_LAST_IO with CF_NOIRQ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this we can get see loops through cpu_io_recompile, in which the cpu makes no progress. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- accel/tcg/cpu-exec.c | 2 +- accel/tcg/tb-maint.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index e2c494e75ef3..c724e8b6f107 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -720,7 +720,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret) && cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0) { /* Execute just one insn to trigger exception pending in the log */ cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT) - | CF_NOIRQ | 1; + | CF_LAST_IO | CF_NOIRQ | 1; } #endif return false; diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c index 32ae8af61cdf..0c3e227409d5 100644 --- a/accel/tcg/tb-maint.c +++ b/accel/tcg/tb-maint.c @@ -1083,7 +1083,8 @@ bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc) if (current_tb_modified) { /* Force execution of one insn next time. */ CPUState *cpu = current_cpu; - cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(current_cpu); + cpu->cflags_next_tb = + 1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(current_cpu); return true; } return false; @@ -1153,7 +1154,8 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages, if (current_tb_modified) { page_collection_unlock(pages); /* Force execution of one insn next time. */ - current_cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(current_cpu); + current_cpu->cflags_next_tb = + 1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(current_cpu); mmap_unlock(); cpu_loop_exit_noexc(current_cpu); } From 18a536f1f8d6222e562f59179e837fdfd8b92718 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 12 Sep 2023 19:08:11 -0700 Subject: [PATCH 032/208] accel/tcg: Always require can_do_io MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Require i/o as the last insn of a TranslationBlock always, not only with icount. This is required for i/o that alters the address space, such as a pci config space write. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1866 Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- accel/tcg/translator.c | 20 +++++++------------- target/mips/tcg/translate.c | 1 - 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index dd507cd4719a..358214d5265e 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -28,12 +28,6 @@ static void set_can_do_io(DisasContextBase *db, bool val) bool translator_io_start(DisasContextBase *db) { - uint32_t cflags = tb_cflags(db->tb); - - if (!(cflags & CF_USE_ICOUNT)) { - return false; - } - set_can_do_io(db, true); /* @@ -86,15 +80,15 @@ static TCGOp *gen_tb_start(DisasContextBase *db, uint32_t cflags) tcg_gen_st16_i32(count, cpu_env, offsetof(ArchCPU, neg.icount_decr.u16.low) - offsetof(ArchCPU, env)); - /* - * cpu->can_do_io is set automatically here at the beginning of - * each translation block. The cost is minimal and only paid for - * -icount, plus it would be very easy to forget doing it in the - * translator. - */ - set_can_do_io(db, db->max_insns == 1 && (cflags & CF_LAST_IO)); } + /* + * cpu->can_do_io is set automatically here at the beginning of + * each translation block. The cost is minimal, plus it would be + * very easy to forget doing it in the translator. + */ + set_can_do_io(db, db->max_insns == 1 && (cflags & CF_LAST_IO)); + return icount_start_insn; } diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 9bb40f1849d6..593fc804588f 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -11212,7 +11212,6 @@ static void gen_branch(DisasContext *ctx, int insn_bytes) /* Branches completion */ clear_branch_hflags(ctx); ctx->base.is_jmp = DISAS_NORETURN; - /* FIXME: Need to clear can_do_io. */ switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) { case MIPS_HFLAG_FBNSLOT: gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes); From bbde656263d80429b51017b077d9b4064ba13b01 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 21 Sep 2023 14:13:06 +0200 Subject: [PATCH 033/208] migration/rdma: Fix save_page method to fail on polling error qemu_rdma_save_page() reports polling error with error_report(), then succeeds anyway. This is because the variable holding the polling status *shadows* the variable the function returns. The latter remains zero. Broken since day one, and duplicated more recently. Fixes: 2da776db4846 (rdma: core logic) Fixes: b390afd8c50b (migration/rdma: Fix out of order wrid) Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Peter Xu Reviewed-by: Li Zhijian Message-ID: <20230921121312.1301864-2-armbru@redhat.com> --- migration/rdma.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/migration/rdma.c b/migration/rdma.c index a2a3db35b1d1..3915d1d7c97d 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -3282,7 +3282,8 @@ static size_t qemu_rdma_save_page(QEMUFile *f, */ while (1) { uint64_t wr_id, wr_id_in; - int ret = qemu_rdma_poll(rdma, rdma->recv_cq, &wr_id_in, NULL); + ret = qemu_rdma_poll(rdma, rdma->recv_cq, &wr_id_in, NULL); + if (ret < 0) { error_report("rdma migration: polling error! %d", ret); goto err; @@ -3297,7 +3298,8 @@ static size_t qemu_rdma_save_page(QEMUFile *f, while (1) { uint64_t wr_id, wr_id_in; - int ret = qemu_rdma_poll(rdma, rdma->send_cq, &wr_id_in, NULL); + ret = qemu_rdma_poll(rdma, rdma->send_cq, &wr_id_in, NULL); + if (ret < 0) { error_report("rdma migration: polling error! %d", ret); goto err; From 7f3de3f02f0bd0eaa3ba4506f9a60c1c35865e93 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 21 Sep 2023 14:13:07 +0200 Subject: [PATCH 034/208] migration: Clean up local variable shadowing Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster Reviewed-by: Peter Xu Reviewed-by: Li Zhijian Message-ID: <20230921121312.1301864-3-armbru@redhat.com> --- migration/block.c | 4 ++-- migration/ram.c | 8 +++----- migration/rdma.c | 8 +++++--- migration/vmstate.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/migration/block.c b/migration/block.c index 86c2256a2bfb..eb6aafeb9e6a 100644 --- a/migration/block.c +++ b/migration/block.c @@ -440,8 +440,8 @@ static int init_blk_migration(QEMUFile *f) /* Can only insert new BDSes now because doing so while iterating block * devices may end up in a deadlock (iterating the new BDSes, too). */ for (i = 0; i < num_bs; i++) { - BlkMigDevState *bmds = bmds_bs[i].bmds; - BlockDriverState *bs = bmds_bs[i].bs; + bmds = bmds_bs[i].bmds; + bs = bmds_bs[i].bs; if (bmds) { ret = blk_insert_bs(bmds->blk, bs, &local_err); diff --git a/migration/ram.c b/migration/ram.c index 9040d66e615e..0c202f8109a3 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -3517,8 +3517,6 @@ int colo_init_ram_cache(void) * we use the same name 'ram_bitmap' as for migration. */ if (ram_bytes_total()) { - RAMBlock *block; - RAMBLOCK_FOREACH_NOT_IGNORED(block) { unsigned long pages = block->max_length >> TARGET_PAGE_BITS; block->bmap = bitmap_new(pages); @@ -3998,12 +3996,12 @@ static int ram_load_precopy(QEMUFile *f) } } if (migrate_ignore_shared()) { - hwaddr addr = qemu_get_be64(f); + hwaddr addr2 = qemu_get_be64(f); if (migrate_ram_is_ignored(block) && - block->mr->addr != addr) { + block->mr->addr != addr2) { error_report("Mismatched GPAs for block %s " "%" PRId64 "!= %" PRId64, - id, (uint64_t)addr, + id, (uint64_t)addr2, (uint64_t)block->mr->addr); ret = -EINVAL; } diff --git a/migration/rdma.c b/migration/rdma.c index 3915d1d7c97d..c78ddfcb74b5 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -1902,9 +1902,11 @@ static int qemu_rdma_exchange_send(RDMAContext *rdma, RDMAControlHeader *head, * by waiting for a READY message. */ if (rdma->control_ready_expected) { - RDMAControlHeader resp; - ret = qemu_rdma_exchange_get_response(rdma, - &resp, RDMA_CONTROL_READY, RDMA_WRID_READY); + RDMAControlHeader resp_ignored; + + ret = qemu_rdma_exchange_get_response(rdma, &resp_ignored, + RDMA_CONTROL_READY, + RDMA_WRID_READY); if (ret < 0) { return ret; } diff --git a/migration/vmstate.c b/migration/vmstate.c index 31842c3afb41..438ea77cfa3b 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -97,7 +97,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, return -EINVAL; } if (vmsd->pre_load) { - int ret = vmsd->pre_load(opaque); + ret = vmsd->pre_load(opaque); if (ret) { return ret; } From e33e66b1b3655d98aadebf7e22eae18077698401 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 21 Sep 2023 14:13:08 +0200 Subject: [PATCH 035/208] ui: Clean up local variable shadowing Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster Reviewed-by: Peter Maydell Message-ID: <20230921121312.1301864-4-armbru@redhat.com> --- ui/gtk.c | 14 +++++++------- ui/spice-display.c | 9 +++++---- ui/vnc-enc-zrle.c.inc | 9 ++++----- ui/vnc-palette.c | 2 -- ui/vnc.c | 12 ++++++------ 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index e09f97a86b7c..3373427c9b89 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -930,8 +930,8 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win); GdkRectangle geometry; - int x = (int)motion->x_root; - int y = (int)motion->y_root; + int xr = (int)motion->x_root; + int yr = (int)motion->y_root; gdk_monitor_get_geometry(monitor, &geometry); @@ -942,13 +942,13 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, * may still be only half way across the screen. Without * this warp, the server pointer would thus appear to hit * an invisible wall */ - if (x <= geometry.x || x - geometry.x >= geometry.width - 1 || - y <= geometry.y || y - geometry.y >= geometry.height - 1) { + if (xr <= geometry.x || xr - geometry.x >= geometry.width - 1 || + yr <= geometry.y || yr - geometry.y >= geometry.height - 1) { GdkDevice *dev = gdk_event_get_device((GdkEvent *)motion); - x = geometry.x + geometry.width / 2; - y = geometry.y + geometry.height / 2; + xr = geometry.x + geometry.width / 2; + yr = geometry.y + geometry.height / 2; - gdk_device_warp(dev, screen, x, y); + gdk_device_warp(dev, screen, xr, yr); s->last_set = FALSE; return FALSE; } diff --git a/ui/spice-display.c b/ui/spice-display.c index 5cc47bd668f4..6eb98a5a5cdb 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -1081,15 +1081,16 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl, } if (render_cursor) { - int x, y; + int ptr_x, ptr_y; + qemu_mutex_lock(&ssd->lock); - x = ssd->ptr_x; - y = ssd->ptr_y; + ptr_x = ssd->ptr_x; + ptr_y = ssd->ptr_y; qemu_mutex_unlock(&ssd->lock); egl_texture_blit(ssd->gls, &ssd->blit_fb, &ssd->guest_fb, !y_0_top); egl_texture_blend(ssd->gls, &ssd->blit_fb, &ssd->cursor_fb, - !y_0_top, x, y, 1.0, 1.0); + !y_0_top, ptr_x, ptr_y, 1.0, 1.0); glFlush(); } diff --git a/ui/vnc-enc-zrle.c.inc b/ui/vnc-enc-zrle.c.inc index a8ca37d05ef3..2ef7501d5216 100644 --- a/ui/vnc-enc-zrle.c.inc +++ b/ui/vnc-enc-zrle.c.inc @@ -153,11 +153,12 @@ static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h, } if (use_rle) { - ZRLE_PIXEL *ptr = data; - ZRLE_PIXEL *end = ptr + w * h; ZRLE_PIXEL *run_start; ZRLE_PIXEL pix; + ptr = data; + end = ptr + w * h; + while (ptr < end) { int len; int index = 0; @@ -198,7 +199,7 @@ static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h, } } else if (use_palette) { /* no RLE */ int bppp; - ZRLE_PIXEL *ptr = data; + ptr = data; /* packed pixels */ @@ -241,8 +242,6 @@ static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h, #endif { #ifdef ZRLE_COMPACT_PIXEL - ZRLE_PIXEL *ptr; - for (ptr = data; ptr < data + w * h; ptr++) { ZRLE_WRITE_PIXEL(vs, *ptr); } diff --git a/ui/vnc-palette.c b/ui/vnc-palette.c index dc7c0ba99724..4e88c412f071 100644 --- a/ui/vnc-palette.c +++ b/ui/vnc-palette.c @@ -86,8 +86,6 @@ int palette_put(VncPalette *palette, uint32_t color) return 0; } if (!entry) { - VncPaletteEntry *entry; - entry = &palette->pool[palette->size]; entry->color = color; entry->idx = idx; diff --git a/ui/vnc.c b/ui/vnc.c index c302bb07a5bc..523eb1f5b0ac 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1584,15 +1584,15 @@ static void vnc_jobs_bh(void *opaque) */ static int vnc_client_read(VncState *vs) { - size_t ret; + size_t sz; #ifdef CONFIG_VNC_SASL if (vs->sasl.conn && vs->sasl.runSSF) - ret = vnc_client_read_sasl(vs); + sz = vnc_client_read_sasl(vs); else #endif /* CONFIG_VNC_SASL */ - ret = vnc_client_read_plain(vs); - if (!ret) { + sz = vnc_client_read_plain(vs); + if (!sz) { if (vs->disconnecting) { vnc_disconnect_finish(vs); return -1; @@ -3118,8 +3118,8 @@ static int vnc_refresh_server_surface(VncDisplay *vd) cmp_bytes = MIN(VNC_DIRTY_PIXELS_PER_BIT * VNC_SERVER_FB_BYTES, server_stride); if (vd->guest.format != VNC_SERVER_FB_FORMAT) { - int width = pixman_image_get_width(vd->server); - tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width); + int w = pixman_image_get_width(vd->server); + tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, w); } else { int guest_bpp = PIXMAN_FORMAT_BPP(pixman_image_get_format(vd->guest.fb)); From 6a0f7ff7dd2034fb167557f0444e1f1851dbd654 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 21 Sep 2023 14:13:09 +0200 Subject: [PATCH 036/208] block/dirty-bitmap: Clean up local variable shadowing Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: rename both the pair of parameters and the pair of local variables. While there, move the local variables to function scope. Suggested-by: Kevin Wolf Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Message-ID: <20230921121312.1301864-5-armbru@redhat.com> --- block/monitor/bitmap-qmp-cmds.c | 19 ++++++++++--------- block/qcow2-bitmap.c | 3 +-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/block/monitor/bitmap-qmp-cmds.c b/block/monitor/bitmap-qmp-cmds.c index 55f778f5af56..70d01a37763f 100644 --- a/block/monitor/bitmap-qmp-cmds.c +++ b/block/monitor/bitmap-qmp-cmds.c @@ -258,37 +258,38 @@ void qmp_block_dirty_bitmap_disable(const char *node, const char *name, bdrv_disable_dirty_bitmap(bitmap); } -BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, +BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *dst_node, + const char *dst_bitmap, BlockDirtyBitmapOrStrList *bms, HBitmap **backup, Error **errp) { BlockDriverState *bs; BdrvDirtyBitmap *dst, *src; BlockDirtyBitmapOrStrList *lst; + const char *src_node, *src_bitmap; HBitmap *local_backup = NULL; GLOBAL_STATE_CODE(); - dst = block_dirty_bitmap_lookup(node, target, &bs, errp); + dst = block_dirty_bitmap_lookup(dst_node, dst_bitmap, &bs, errp); if (!dst) { return NULL; } for (lst = bms; lst; lst = lst->next) { switch (lst->value->type) { - const char *name, *node; case QTYPE_QSTRING: - name = lst->value->u.local; - src = bdrv_find_dirty_bitmap(bs, name); + src_bitmap = lst->value->u.local; + src = bdrv_find_dirty_bitmap(bs, src_bitmap); if (!src) { - error_setg(errp, "Dirty bitmap '%s' not found", name); + error_setg(errp, "Dirty bitmap '%s' not found", src_bitmap); goto fail; } break; case QTYPE_QDICT: - node = lst->value->u.external.node; - name = lst->value->u.external.name; - src = block_dirty_bitmap_lookup(node, name, NULL, errp); + src_node = lst->value->u.external.node; + src_bitmap = lst->value->u.external.name; + src = block_dirty_bitmap_lookup(src_node, src_bitmap, NULL, errp); if (!src) { goto fail; } diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index 037fa2d4351a..ffd5cd3b23c3 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -1555,7 +1555,6 @@ bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, FOR_EACH_DIRTY_BITMAP(bs, bitmap) { const char *name = bdrv_dirty_bitmap_name(bitmap); uint32_t granularity = bdrv_dirty_bitmap_granularity(bitmap); - Qcow2Bitmap *bm; if (!bdrv_dirty_bitmap_get_persistence(bitmap) || bdrv_dirty_bitmap_inconsistent(bitmap)) { @@ -1625,7 +1624,7 @@ bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, /* allocate clusters and store bitmaps */ QSIMPLEQ_FOREACH(bm, bm_list, entry) { - BdrvDirtyBitmap *bitmap = bm->dirty_bitmap; + bitmap = bm->dirty_bitmap; if (bitmap == NULL || bdrv_dirty_bitmap_readonly(bitmap)) { continue; From d25b99c72b0178ce0e0c766b07011102dbbacf6a Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 21 Sep 2023 14:13:10 +0200 Subject: [PATCH 037/208] block/vdi: Clean up local variable shadowing Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster Reviewed-by: Stefan Hajnoczi Reviewed-by: Kevin Wolf Message-ID: <20230921121312.1301864-6-armbru@redhat.com> --- block/vdi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/block/vdi.c b/block/vdi.c index 6c35309e04aa..934e1b849b66 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -634,7 +634,6 @@ vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, bmap_entry = le32_to_cpu(s->bmap[block_index]); if (!VDI_IS_ALLOCATED(bmap_entry)) { /* Allocate new block and write to it. */ - uint64_t data_offset; qemu_co_rwlock_upgrade(&s->bmap_lock); bmap_entry = le32_to_cpu(s->bmap[block_index]); if (VDI_IS_ALLOCATED(bmap_entry)) { @@ -700,7 +699,7 @@ vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, /* One or more new blocks were allocated. */ VdiHeader *header; uint8_t *base; - uint64_t offset; + uint64_t bmap_offset; uint32_t n_sectors; g_free(block); @@ -723,11 +722,11 @@ vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, bmap_first /= (SECTOR_SIZE / sizeof(uint32_t)); bmap_last /= (SECTOR_SIZE / sizeof(uint32_t)); n_sectors = bmap_last - bmap_first + 1; - offset = s->bmap_sector + bmap_first; + bmap_offset = s->bmap_sector + bmap_first; base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE; logout("will write %u block map sectors starting from entry %u\n", n_sectors, bmap_first); - ret = bdrv_co_pwrite(bs->file, offset * SECTOR_SIZE, + ret = bdrv_co_pwrite(bs->file, bmap_offset * SECTOR_SIZE, n_sectors * SECTOR_SIZE, base, 0); } From fb2575f95411644abe7f0606594035b63a5132ad Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 21 Sep 2023 14:13:11 +0200 Subject: [PATCH 038/208] block: Clean up local variable shadowing Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster Reviewed-by: Stefan Hajnoczi Acked-by: Anthony PERARD Acked-by: Ilya Dryomov Reviewed-by: Kevin Wolf Message-ID: <20230921121312.1301864-7-armbru@redhat.com> --- block.c | 9 +++++---- block/rbd.c | 2 +- block/stream.c | 1 - block/vvfat.c | 35 ++++++++++++++++++----------------- hw/block/xen-block.c | 6 +++--- 5 files changed, 27 insertions(+), 26 deletions(-) diff --git a/block.c b/block.c index e7f349b25c03..af04c8ac6f3e 100644 --- a/block.c +++ b/block.c @@ -3072,18 +3072,19 @@ bdrv_attach_child_common(BlockDriverState *child_bs, &local_err); if (ret < 0 && child_class->change_aio_ctx) { - Transaction *tran = tran_new(); + Transaction *aio_ctx_tran = tran_new(); GHashTable *visited = g_hash_table_new(NULL, NULL); bool ret_child; g_hash_table_add(visited, new_child); ret_child = child_class->change_aio_ctx(new_child, child_ctx, - visited, tran, NULL); + visited, aio_ctx_tran, + NULL); if (ret_child == true) { error_free(local_err); ret = 0; } - tran_finalize(tran, ret_child == true ? 0 : -1); + tran_finalize(aio_ctx_tran, ret_child == true ? 0 : -1); g_hash_table_destroy(visited); } @@ -6208,12 +6209,12 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name), QLIST_FOREACH(drv, &bdrv_drivers, list) { if (drv->format_name) { bool found = false; - int i = count; if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, read_only)) { continue; } + i = count; while (formats && i && !found) { found = !strcmp(formats[--i], drv->format_name); } diff --git a/block/rbd.c b/block/rbd.c index 978671411ec7..472ca05cbae7 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -1290,7 +1290,7 @@ static int coroutine_fn qemu_rbd_start_co(BlockDriverState *bs, * operations that exceed the current size. */ if (offset + bytes > s->image_size) { - int r = qemu_rbd_resize(bs, offset + bytes); + r = qemu_rbd_resize(bs, offset + bytes); if (r < 0) { return r; } diff --git a/block/stream.c b/block/stream.c index e4da214f1fb2..133cb72fb4c2 100644 --- a/block/stream.c +++ b/block/stream.c @@ -292,7 +292,6 @@ void stream_start(const char *job_id, BlockDriverState *bs, /* Make sure that the image is opened in read-write mode */ bs_read_only = bdrv_is_read_only(bs); if (bs_read_only) { - int ret; /* Hold the chain during reopen */ if (bdrv_freeze_backing_chain(bs, above_base, errp) < 0) { return; diff --git a/block/vvfat.c b/block/vvfat.c index 0ddc91fc096a..856b479c9186 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -777,7 +777,6 @@ static int read_directory(BDRVVVFATState* s, int mapping_index) while((entry=readdir(dir))) { unsigned int length=strlen(dirname)+2+strlen(entry->d_name); char* buffer; - direntry_t* direntry; struct stat st; int is_dot=!strcmp(entry->d_name,"."); int is_dotdot=!strcmp(entry->d_name,".."); @@ -857,7 +856,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index) /* fill with zeroes up to the end of the cluster */ while(s->directory.next%(0x10*s->sectors_per_cluster)) { - direntry_t* direntry=array_get_next(&(s->directory)); + direntry = array_get_next(&(s->directory)); memset(direntry,0,sizeof(direntry_t)); } @@ -1962,24 +1961,24 @@ get_cluster_count_for_direntry(BDRVVVFATState* s, direntry_t* direntry, const ch * This is horribly inefficient, but that is okay, since * it is rarely executed, if at all. */ - int64_t offset = cluster2sector(s, cluster_num); + int64_t offs = cluster2sector(s, cluster_num); vvfat_close_current_file(s); for (i = 0; i < s->sectors_per_cluster; i++) { int res; res = bdrv_is_allocated(s->qcow->bs, - (offset + i) * BDRV_SECTOR_SIZE, + (offs + i) * BDRV_SECTOR_SIZE, BDRV_SECTOR_SIZE, NULL); if (res < 0) { return -1; } if (!res) { - res = vvfat_read(s->bs, offset, s->cluster_buffer, 1); + res = vvfat_read(s->bs, offs, s->cluster_buffer, 1); if (res) { return -1; } - res = bdrv_co_pwrite(s->qcow, offset * BDRV_SECTOR_SIZE, + res = bdrv_co_pwrite(s->qcow, offs * BDRV_SECTOR_SIZE, BDRV_SECTOR_SIZE, s->cluster_buffer, 0); if (res < 0) { @@ -2467,8 +2466,9 @@ commit_direntries(BDRVVVFATState* s, int dir_index, int parent_mapping_index) for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) { direntry_t *first_direntry; - void* direntry = array_get(&(s->directory), current_dir_index); - int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry, + + direntry = array_get(&(s->directory), current_dir_index); + ret = vvfat_read(s->bs, cluster2sector(s, c), (uint8_t *)direntry, s->sectors_per_cluster); if (ret) return ret; @@ -2690,12 +2690,12 @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s) direntry_t* direntry = array_get(&(s->directory), mapping->info.dir.first_dir_index); uint32_t c = mapping->begin; - int i = 0; + int j = 0; /* recurse */ while (!fat_eof(s, c)) { do { - direntry_t* d = direntry + i; + direntry_t *d = direntry + j; if (is_file(d) || (is_directory(d) && !is_dot(d))) { int l; @@ -2716,8 +2716,8 @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s) schedule_rename(s, m->begin, new_path); } - i++; - } while((i % (0x10 * s->sectors_per_cluster)) != 0); + j++; + } while (j % (0x10 * s->sectors_per_cluster) != 0); c = fat_get(s, c); } } @@ -2804,16 +2804,16 @@ static int coroutine_fn GRAPH_RDLOCK handle_commits(BDRVVVFATState* s) int begin = commit->param.new_file.first_cluster; mapping_t* mapping = find_mapping_for_cluster(s, begin); direntry_t* entry; - int i; + int j; /* find direntry */ - for (i = 0; i < s->directory.next; i++) { - entry = array_get(&(s->directory), i); + for (j = 0; j < s->directory.next; j++) { + entry = array_get(&(s->directory), j); if (is_file(entry) && begin_of_direntry(entry) == begin) break; } - if (i >= s->directory.next) { + if (j >= s->directory.next) { fail = -6; continue; } @@ -2833,8 +2833,9 @@ static int coroutine_fn GRAPH_RDLOCK handle_commits(BDRVVVFATState* s) mapping->mode = MODE_NORMAL; mapping->info.file.offset = 0; - if (commit_one_file(s, i, 0)) + if (commit_one_file(s, j, 0)) { fail = -7; + } break; } diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index 3906b9058bca..a07cd7eb5df5 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -369,7 +369,7 @@ static void xen_block_get_vdev(Object *obj, Visitor *v, const char *name, case XEN_BLOCK_VDEV_TYPE_XVD: case XEN_BLOCK_VDEV_TYPE_HD: case XEN_BLOCK_VDEV_TYPE_SD: { - char *name = disk_to_vbd_name(vdev->disk); + char *vbd_name = disk_to_vbd_name(vdev->disk); str = g_strdup_printf("%s%s%lu", (vdev->type == XEN_BLOCK_VDEV_TYPE_XVD) ? @@ -377,8 +377,8 @@ static void xen_block_get_vdev(Object *obj, Visitor *v, const char *name, (vdev->type == XEN_BLOCK_VDEV_TYPE_HD) ? "hd" : "sd", - name, vdev->partition); - g_free(name); + vbd_name, vdev->partition); + g_free(vbd_name); break; } default: From bb71846325e23d884ca4ff1bcc95aaead0131a5a Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 21 Sep 2023 14:13:12 +0200 Subject: [PATCH 039/208] qobject atomics osdep: Make a few macros more hygienic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Variables declared in macros can shadow other variables. Much of the time, this is harmless, e.g.: #define _FDT(exp) \ do { \ int ret = (exp); \ if (ret < 0) { \ error_report("error creating device tree: %s: %s", \ #exp, fdt_strerror(ret)); \ exit(1); \ } \ } while (0) Harmless shadowing in h_client_architecture_support(): target_ulong ret; [...] ret = do_client_architecture_support(cpu, spapr, vec, fdt_bufsize); if (ret == H_SUCCESS) { _FDT((fdt_pack(spapr->fdt_blob))); [...] } return ret; However, we can get in trouble when the shadowed variable is used in a macro argument: #define QOBJECT(obj) ({ \ typeof(obj) o = (obj); \ o ? container_of(&(o)->base, QObject, base) : NULL; \ }) QOBJECT(o) expands into ({ ---> typeof(o) o = (o); o ? container_of(&(o)->base, QObject, base) : NULL; }) Unintended variable name capture at --->. We'd be saved by -Winit-self. But I could certainly construct more elaborate death traps that don't trigger it. To reduce the risk of trapping ourselves, we use variable names in macros that no sane person would use elsewhere. Here's our actual definition of QOBJECT(): #define QOBJECT(obj) ({ \ typeof(obj) _obj = (obj); \ _obj ? container_of(&(_obj)->base, QObject, base) : NULL; \ }) Works well enough until we nest macro calls. For instance, with #define qobject_ref(obj) ({ \ typeof(obj) _obj = (obj); \ qobject_ref_impl(QOBJECT(_obj)); \ _obj; \ }) the expression qobject_ref(obj) expands into ({ typeof(obj) _obj = (obj); qobject_ref_impl( ({ ---> typeof(_obj) _obj = (_obj); _obj ? container_of(&(_obj)->base, QObject, base) : NULL; })); _obj; }) Unintended variable name capture at --->. The only reliable way to prevent unintended variable name capture is -Wshadow. One blocker for enabling it is shadowing hiding in function-like macros like qdict_put(dict, "name", qobject_ref(...)) qdict_put() wraps its last argument in QOBJECT(), and the last argument here contains another QOBJECT(). Use dark preprocessor sorcery to make the macros that give us this problem use different variable names on every call. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Message-ID: <20230921121312.1301864-8-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé --- include/qapi/qmp/qobject.h | 10 ++++++++-- include/qemu/atomic.h | 17 ++++++++++++----- include/qemu/compiler.h | 3 +++ include/qemu/osdep.h | 27 ++++++++++++++++++++------- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h index 9003b71fd32d..89b97d88bcab 100644 --- a/include/qapi/qmp/qobject.h +++ b/include/qapi/qmp/qobject.h @@ -45,10 +45,16 @@ struct QObject { struct QObjectBase_ base; }; -#define QOBJECT(obj) ({ \ +/* + * Preprocessor sorcery ahead: use a different identifier for the + * local variable in each expansion, so we can nest macro calls + * without shadowing variables. + */ +#define QOBJECT_INTERNAL(obj, _obj) ({ \ typeof(obj) _obj = (obj); \ - _obj ? container_of(&(_obj)->base, QObject, base) : NULL; \ + _obj ? container_of(&_obj->base, QObject, base) : NULL; \ }) +#define QOBJECT(obj) QOBJECT_INTERNAL((obj), MAKE_IDENTFIER(_obj)) /* Required for qobject_to() */ #define QTYPE_CAST_TO_QNull QTYPE_QNULL diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index d95612f7a084..f1d3d1702a93 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -157,13 +157,20 @@ smp_read_barrier_depends(); #endif -#define qatomic_rcu_read(ptr) \ - ({ \ +/* + * Preprocessor sorcery ahead: use a different identifier for the + * local variable in each expansion, so we can nest macro calls + * without shadowing variables. + */ +#define qatomic_rcu_read_internal(ptr, _val) \ + ({ \ qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \ - typeof_strip_qual(*ptr) _val; \ - qatomic_rcu_read__nocheck(ptr, &_val); \ - _val; \ + typeof_strip_qual(*ptr) _val; \ + qatomic_rcu_read__nocheck(ptr, &_val); \ + _val; \ }) +#define qatomic_rcu_read(ptr) \ + qatomic_rcu_read_internal((ptr), MAKE_IDENTFIER(_val)) #define qatomic_rcu_set(ptr, i) do { \ qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \ diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h index 7fda29b445f4..7f1bbbf05f4f 100644 --- a/include/qemu/compiler.h +++ b/include/qemu/compiler.h @@ -37,6 +37,9 @@ #define tostring(s) #s #endif +/* Expands into an identifier stemN, where N is another number each time */ +#define MAKE_IDENTFIER(stem) glue(stem, __COUNTER__) + #ifndef likely #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index e4a4eb2d6135..18b940db7585 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -383,19 +383,28 @@ void QEMU_ERROR("code path is reachable") * determined by the pre-processor instead of the compiler, you'll * have to open-code it. Sadly, Coverity is severely confused by the * constant variants, so we have to dumb things down there. + * + * Preprocessor sorcery ahead: use different identifiers for the local + * variables in each expansion, so we can nest macro calls without + * shadowing variables. */ -#undef MIN -#define MIN(a, b) \ +#define MIN_INTERNAL(a, b, _a, _b) \ ({ \ typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ _a < _b ? _a : _b; \ }) -#undef MAX -#define MAX(a, b) \ +#undef MIN +#define MIN(a, b) \ + MIN_INTERNAL((a), (b), MAKE_IDENTFIER(_a), MAKE_IDENTFIER(_b)) + +#define MAX_INTERNAL(a, b, _a, _b) \ ({ \ typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ _a > _b ? _a : _b; \ }) +#undef MAX +#define MAX(a, b) \ + MAX_INTERNAL((a), (b), MAKE_IDENTFIER(_a), MAKE_IDENTFIER(_b)) #ifdef __COVERITY__ # define MIN_CONST(a, b) ((a) < (b) ? (a) : (b)) @@ -416,14 +425,18 @@ void QEMU_ERROR("code path is reachable") /* * Minimum function that returns zero only if both values are zero. * Intended for use with unsigned values only. + * + * Preprocessor sorcery ahead: use different identifiers for the local + * variables in each expansion, so we can nest macro calls without + * shadowing variables. */ -#ifndef MIN_NON_ZERO -#define MIN_NON_ZERO(a, b) \ +#define MIN_NON_ZERO_INTERNAL(a, b, _a, _b) \ ({ \ typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ _a == 0 ? _b : (_b == 0 || _b > _a) ? _a : _b; \ }) -#endif +#define MIN_NON_ZERO(a, b) \ + MIN_NON_ZERO_INTERNAL((a), (b), MAKE_IDENTFIER(_a), MAKE_IDENTFIER(_b)) /* * Round number down to multiple. Safe when m is not a power of 2 (see From 6d559996447e544e93e036fc4c87f2f64defef5e Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Wed, 13 Sep 2023 12:53:18 +0200 Subject: [PATCH 040/208] hw/tricore: Log failing test in testdevice Signed-off-by: Bastian Koppelmann Message-ID: <20230913105326.40832-3-kbastian@mail.uni-paderborn.de> --- hw/tricore/tricore_testdevice.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/tricore/tricore_testdevice.c b/hw/tricore/tricore_testdevice.c index a1563aa56890..9028d970b00f 100644 --- a/hw/tricore/tricore_testdevice.c +++ b/hw/tricore/tricore_testdevice.c @@ -16,6 +16,7 @@ */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "hw/sysbus.h" #include "hw/qdev-properties.h" #include "hw/tricore/tricore_testdevice.h" @@ -23,6 +24,9 @@ static void tricore_testdevice_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { + if (value != 0) { + qemu_log_mask(LOG_GUEST_ERROR, "Test %" PRIu64 " failed!\n", value); + } exit(value); } From 76bc63d7eda821e0a82e0ba0a5ad1ad5c52c8d5f Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Wed, 13 Sep 2023 12:53:19 +0200 Subject: [PATCH 041/208] tests/tcg: Reset result register after each test some insns use the result register implicitly as an input. Thus, we could end up with data from the previous insn spilling over. Signed-off-by: Bastian Koppelmann Message-ID: <20230913105326.40832-4-kbastian@mail.uni-paderborn.de> --- tests/tcg/tricore/asm/macros.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/tcg/tricore/asm/macros.h b/tests/tcg/tricore/asm/macros.h index 0f349dbf1e17..e831f737216e 100644 --- a/tests/tcg/tricore/asm/macros.h +++ b/tests/tcg/tricore/asm/macros.h @@ -46,7 +46,8 @@ test_ ## num: \ code; \ LI(DREG_CORRECT_RESULT, correct) \ mov DREG_TEST_NUM, num; \ - jne testreg, DREG_CORRECT_RESULT, fail \ + jne testreg, DREG_CORRECT_RESULT, fail; \ + mov testreg, 0 #define TEST_CASE_E(num, correct_lo, correct_hi, code...) \ test_ ## num: \ From 824b2cb39c3c7dfa93f50d99d8bbd0c6d217ce24 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Wed, 13 Sep 2023 12:53:25 +0200 Subject: [PATCH 042/208] target/tricore: Remove CSFRs from cpu.h these are already defined in 'csfr.h.inc'. We don't need to duplicate these registers. Signed-off-by: Bastian Koppelmann Message-ID: <20230913105326.40832-10-kbastian@mail.uni-paderborn.de> --- target/tricore/cpu.h | 143 +++---------------------------------------- 1 file changed, 9 insertions(+), 134 deletions(-) diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h index 3708405be898..1cace96b0136 100644 --- a/target/tricore/cpu.h +++ b/target/tricore/cpu.h @@ -30,150 +30,25 @@ typedef struct CPUArchState { /* GPR Register */ uint32_t gpr_a[16]; uint32_t gpr_d[16]; - /* CSFR Register */ - uint32_t PCXI; /* Frequently accessed PSW_USB bits are stored separately for efficiency. This contains all the other bits. Use psw_{read,write} to access the whole PSW. */ uint32_t PSW; - - /* PSW flag cache for faster execution - */ + /* PSW flag cache for faster execution */ uint32_t PSW_USB_C; uint32_t PSW_USB_V; /* Only if bit 31 set, then flag is set */ uint32_t PSW_USB_SV; /* Only if bit 31 set, then flag is set */ uint32_t PSW_USB_AV; /* Only if bit 31 set, then flag is set. */ uint32_t PSW_USB_SAV; /* Only if bit 31 set, then flag is set. */ - uint32_t PC; - uint32_t SYSCON; - uint32_t CPU_ID; - uint32_t CORE_ID; - uint32_t BIV; - uint32_t BTV; - uint32_t ISP; - uint32_t ICR; - uint32_t FCX; - uint32_t LCX; - uint32_t COMPAT; - - /* Mem Protection Register */ - uint32_t DPR0_0L; - uint32_t DPR0_0U; - uint32_t DPR0_1L; - uint32_t DPR0_1U; - uint32_t DPR0_2L; - uint32_t DPR0_2U; - uint32_t DPR0_3L; - uint32_t DPR0_3U; - - uint32_t DPR1_0L; - uint32_t DPR1_0U; - uint32_t DPR1_1L; - uint32_t DPR1_1U; - uint32_t DPR1_2L; - uint32_t DPR1_2U; - uint32_t DPR1_3L; - uint32_t DPR1_3U; - - uint32_t DPR2_0L; - uint32_t DPR2_0U; - uint32_t DPR2_1L; - uint32_t DPR2_1U; - uint32_t DPR2_2L; - uint32_t DPR2_2U; - uint32_t DPR2_3L; - uint32_t DPR2_3U; - - uint32_t DPR3_0L; - uint32_t DPR3_0U; - uint32_t DPR3_1L; - uint32_t DPR3_1U; - uint32_t DPR3_2L; - uint32_t DPR3_2U; - uint32_t DPR3_3L; - uint32_t DPR3_3U; - - uint32_t CPR0_0L; - uint32_t CPR0_0U; - uint32_t CPR0_1L; - uint32_t CPR0_1U; - uint32_t CPR0_2L; - uint32_t CPR0_2U; - uint32_t CPR0_3L; - uint32_t CPR0_3U; - - uint32_t CPR1_0L; - uint32_t CPR1_0U; - uint32_t CPR1_1L; - uint32_t CPR1_1U; - uint32_t CPR1_2L; - uint32_t CPR1_2U; - uint32_t CPR1_3L; - uint32_t CPR1_3U; - - uint32_t CPR2_0L; - uint32_t CPR2_0U; - uint32_t CPR2_1L; - uint32_t CPR2_1U; - uint32_t CPR2_2L; - uint32_t CPR2_2U; - uint32_t CPR2_3L; - uint32_t CPR2_3U; - - uint32_t CPR3_0L; - uint32_t CPR3_0U; - uint32_t CPR3_1L; - uint32_t CPR3_1U; - uint32_t CPR3_2L; - uint32_t CPR3_2U; - uint32_t CPR3_3L; - uint32_t CPR3_3U; - - uint32_t DPM0; - uint32_t DPM1; - uint32_t DPM2; - uint32_t DPM3; - - uint32_t CPM0; - uint32_t CPM1; - uint32_t CPM2; - uint32_t CPM3; - - /* Memory Management Registers */ - uint32_t MMU_CON; - uint32_t MMU_ASI; - uint32_t MMU_TVA; - uint32_t MMU_TPA; - uint32_t MMU_TPX; - uint32_t MMU_TFA; - /* {1.3.1 only */ - uint32_t BMACON; - uint32_t SMACON; - uint32_t DIEAR; - uint32_t DIETR; - uint32_t CCDIER; - uint32_t MIECON; - uint32_t PIEAR; - uint32_t PIETR; - uint32_t CCPIER; - /*} */ - /* Debug Registers */ - uint32_t DBGSR; - uint32_t EXEVT; - uint32_t CREVT; - uint32_t SWEVT; - uint32_t TR0EVT; - uint32_t TR1EVT; - uint32_t DMS; - uint32_t DCX; - uint32_t DBGTCR; - uint32_t CCTRL; - uint32_t CCNT; - uint32_t ICNT; - uint32_t M1CNT; - uint32_t M2CNT; - uint32_t M3CNT; +#define R(ADDR, NAME, FEATURE) uint32_t NAME; +#define A(ADDR, NAME, FEATURE) uint32_t NAME; +#define E(ADDR, NAME, FEATURE) uint32_t NAME; +#include "csfr.h.inc" +#undef R +#undef A +#undef E + /* Floating Point Registers */ float_status fp_status; From ceada000846b0cd81c578b1da9f76d0c59536654 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Wed, 13 Sep 2023 12:53:26 +0200 Subject: [PATCH 043/208] target/tricore: Change effective address (ea) to target_ulong as this is an effective address and those cannot be signed, it should not be a signed integer. Signed-off-by: Bastian Koppelmann Message-ID: <20230913105326.40832-11-kbastian@mail.uni-paderborn.de> --- target/tricore/op_helper.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c index 0cf8eb50bdc6..ba9c4444b394 100644 --- a/target/tricore/op_helper.c +++ b/target/tricore/op_helper.c @@ -2458,7 +2458,7 @@ static bool cdc_zero(target_ulong *psw) return count == 0; } -static void save_context_upper(CPUTriCoreState *env, int ea) +static void save_context_upper(CPUTriCoreState *env, target_ulong ea) { cpu_stl_data(env, ea, env->PCXI); cpu_stl_data(env, ea+4, psw_read(env)); @@ -2478,7 +2478,7 @@ static void save_context_upper(CPUTriCoreState *env, int ea) cpu_stl_data(env, ea+60, env->gpr_d[15]); } -static void save_context_lower(CPUTriCoreState *env, int ea) +static void save_context_lower(CPUTriCoreState *env, target_ulong ea) { cpu_stl_data(env, ea, env->PCXI); cpu_stl_data(env, ea+4, env->gpr_a[11]); @@ -2498,7 +2498,7 @@ static void save_context_lower(CPUTriCoreState *env, int ea) cpu_stl_data(env, ea+60, env->gpr_d[7]); } -static void restore_context_upper(CPUTriCoreState *env, int ea, +static void restore_context_upper(CPUTriCoreState *env, target_ulong ea, target_ulong *new_PCXI, target_ulong *new_PSW) { *new_PCXI = cpu_ldl_data(env, ea); @@ -2519,7 +2519,7 @@ static void restore_context_upper(CPUTriCoreState *env, int ea, env->gpr_d[15] = cpu_ldl_data(env, ea+60); } -static void restore_context_lower(CPUTriCoreState *env, int ea, +static void restore_context_lower(CPUTriCoreState *env, target_ulong ea, target_ulong *ra, target_ulong *pcxi) { *pcxi = cpu_ldl_data(env, ea); @@ -2763,26 +2763,26 @@ void helper_rfm(CPUTriCoreState *env) } } -void helper_ldlcx(CPUTriCoreState *env, uint32_t ea) +void helper_ldlcx(CPUTriCoreState *env, target_ulong ea) { uint32_t dummy; /* insn doesn't load PCXI and RA */ restore_context_lower(env, ea, &dummy, &dummy); } -void helper_lducx(CPUTriCoreState *env, uint32_t ea) +void helper_lducx(CPUTriCoreState *env, target_ulong ea) { uint32_t dummy; /* insn doesn't load PCXI and PSW */ restore_context_upper(env, ea, &dummy, &dummy); } -void helper_stlcx(CPUTriCoreState *env, uint32_t ea) +void helper_stlcx(CPUTriCoreState *env, target_ulong ea) { save_context_lower(env, ea); } -void helper_stucx(CPUTriCoreState *env, uint32_t ea) +void helper_stucx(CPUTriCoreState *env, target_ulong ea) { save_context_upper(env, ea); } From 35ed01ba5448208695ada5fa20a13c0a4689a1c1 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Tue, 26 Sep 2023 16:25:02 -0300 Subject: [PATCH 044/208] optionrom: Remove build-id section Our linker script for optionroms specifies only the placement of the .text section, leaving the linker free to place the remaining sections at arbitrary places in the file. Since at least binutils 2.39, the .note.gnu.build-id section is now being placed at the start of the file, which causes label addresses to be shifted. For linuxboot_dma.bin that means that the PnP header (among others) will not be found when determining the type of ROM at optionrom_setup(): (0x1c is the label _pnph, where the magic "PnP" is) $ xxd /usr/share/qemu/linuxboot_dma.bin | grep "PnP" 00000010: 0000 0000 0000 0000 0000 1c00 2450 6e50 ............$PnP $ xxd pc-bios/optionrom/linuxboot_dma.bin | grep "PnP" 00000010: 0000 0000 0000 0000 0000 4c00 2450 6e50 ............$PnP ^bad Using a freshly built linuxboot_dma.bin ROM results in a broken boot: SeaBIOS (version rel-1.16.2-0-gea1b7a073390-prebuilt.qemu.org) Booting from Hard Disk... Boot failed: could not read the boot disk Booting from Floppy... Boot failed: could not read the boot disk No bootable device. We're not using the build-id section, so pass the --build-id=none option to the linker to remove it entirely. Note: In theory, this same issue could happen with any other section. The ideal solution would be to have all unused sections discarded in the linker script. However that would be a larger change, specially for the pvh rom which uses the .bss and COMMON sections so I'm addressing only the immediate issue here. Reported-by: Vasiliy Ulyanov Signed-off-by: Fabiano Rosas Reviewed-by: Thomas Huth Message-ID: <20230926192502.15986-1-farosas@suse.de> Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini --- pc-bios/optionrom/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile index b1fff0ba6c84..30d07026c790 100644 --- a/pc-bios/optionrom/Makefile +++ b/pc-bios/optionrom/Makefile @@ -36,7 +36,7 @@ config-cc.mak: Makefile $(call cc-option,-Wno-array-bounds)) 3> config-cc.mak -include config-cc.mak -override LDFLAGS = -nostdlib -Wl,-T,$(SRC_DIR)/flat.lds +override LDFLAGS = -nostdlib -Wl,--build-id=none,-T,$(SRC_DIR)/flat.lds pvh.img: pvh.o pvh_main.o From 7191f24c7fcfbc1216d09214122582f4f9d699db Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 1 Dec 2022 19:27:28 +0900 Subject: [PATCH 045/208] accel/kvm/kvm-all: Handle register access errors A register access error typically means something seriously wrong happened so that anything bad can happen after that and recovery is impossible. Even failing one register access is catastorophic as architecture-specific code are not written so that it torelates such failures. Make sure the VM stop and nothing worse happens if such an error occurs. Signed-off-by: Akihiko Odaki Message-ID: <20221201102728.69751-1-akihiko.odaki@daynix.com> Signed-off-by: Paolo Bonzini --- accel/kvm/kvm-all.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index ff1578bb32b9..72e1d1141c48 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -2851,7 +2851,13 @@ bool kvm_cpu_check_are_resettable(void) static void do_kvm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) { if (!cpu->vcpu_dirty) { - kvm_arch_get_registers(cpu); + int ret = kvm_arch_get_registers(cpu); + if (ret) { + error_report("Failed to get registers: %s", strerror(-ret)); + cpu_dump_state(cpu, stderr, CPU_DUMP_CODE); + vm_stop(RUN_STATE_INTERNAL_ERROR); + } + cpu->vcpu_dirty = true; } } @@ -2865,7 +2871,13 @@ void kvm_cpu_synchronize_state(CPUState *cpu) static void do_kvm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg) { - kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE); + int ret = kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE); + if (ret) { + error_report("Failed to put registers after reset: %s", strerror(-ret)); + cpu_dump_state(cpu, stderr, CPU_DUMP_CODE); + vm_stop(RUN_STATE_INTERNAL_ERROR); + } + cpu->vcpu_dirty = false; } @@ -2876,7 +2888,12 @@ void kvm_cpu_synchronize_post_reset(CPUState *cpu) static void do_kvm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) { - kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE); + int ret = kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE); + if (ret) { + error_report("Failed to put registers after init: %s", strerror(-ret)); + exit(1); + } + cpu->vcpu_dirty = false; } @@ -2969,7 +2986,14 @@ int kvm_cpu_exec(CPUState *cpu) MemTxAttrs attrs; if (cpu->vcpu_dirty) { - kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE); + ret = kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE); + if (ret) { + error_report("Failed to put registers after init: %s", + strerror(-ret)); + ret = -1; + break; + } + cpu->vcpu_dirty = false; } From fa4ec9ffda74dc5970ae5a104588dba0ffb49c9f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 22 Sep 2023 11:52:11 +0200 Subject: [PATCH 046/208] e1000: remove old compatibility code This code is not needed anymore in the supported machine types. Signed-off-by: Paolo Bonzini --- hw/net/e1000.c | 81 +++++++++++++++++--------------------------------- 1 file changed, 28 insertions(+), 53 deletions(-) diff --git a/hw/net/e1000.c b/hw/net/e1000.c index 093c2d453155..548bcabcbba2 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -127,13 +127,9 @@ struct E1000State_st { QEMUTimer *flush_queue_timer; /* Compatibility flags for migration to/from qemu 1.3.0 and older */ -#define E1000_FLAG_AUTONEG_BIT 0 -#define E1000_FLAG_MIT_BIT 1 #define E1000_FLAG_MAC_BIT 2 #define E1000_FLAG_TSO_BIT 3 #define E1000_FLAG_VET_BIT 4 -#define E1000_FLAG_AUTONEG (1 << E1000_FLAG_AUTONEG_BIT) -#define E1000_FLAG_MIT (1 << E1000_FLAG_MIT_BIT) #define E1000_FLAG_MAC (1 << E1000_FLAG_MAC_BIT) #define E1000_FLAG_TSO (1 << E1000_FLAG_TSO_BIT) #define E1000_FLAG_VET (1 << E1000_FLAG_VET_BIT) @@ -180,7 +176,7 @@ e1000_autoneg_done(E1000State *s) static bool have_autoneg(E1000State *s) { - return chkflag(AUTONEG) && (s->phy_reg[MII_BMCR] & MII_BMCR_AUTOEN); + return (s->phy_reg[MII_BMCR] & MII_BMCR_AUTOEN); } static void @@ -308,35 +304,34 @@ set_interrupt_cause(E1000State *s, int index, uint32_t val) if (s->mit_timer_on) { return; } - if (chkflag(MIT)) { - /* Compute the next mitigation delay according to pending - * interrupts and the current values of RADV (provided - * RDTR!=0), TADV and ITR. - * Then rearm the timer. - */ - mit_delay = 0; - if (s->mit_ide && - (pending_ints & (E1000_ICR_TXQE | E1000_ICR_TXDW))) { - mit_update_delay(&mit_delay, s->mac_reg[TADV] * 4); - } - if (s->mac_reg[RDTR] && (pending_ints & E1000_ICS_RXT0)) { - mit_update_delay(&mit_delay, s->mac_reg[RADV] * 4); - } - mit_update_delay(&mit_delay, s->mac_reg[ITR]); - - /* - * According to e1000 SPEC, the Ethernet controller guarantees - * a maximum observable interrupt rate of 7813 interrupts/sec. - * Thus if mit_delay < 500 then the delay should be set to the - * minimum delay possible which is 500. - */ - mit_delay = (mit_delay < 500) ? 500 : mit_delay; - - s->mit_timer_on = 1; - timer_mod(s->mit_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - mit_delay * 256); - s->mit_ide = 0; + + /* Compute the next mitigation delay according to pending + * interrupts and the current values of RADV (provided + * RDTR!=0), TADV and ITR. + * Then rearm the timer. + */ + mit_delay = 0; + if (s->mit_ide && + (pending_ints & (E1000_ICR_TXQE | E1000_ICR_TXDW))) { + mit_update_delay(&mit_delay, s->mac_reg[TADV] * 4); } + if (s->mac_reg[RDTR] && (pending_ints & E1000_ICS_RXT0)) { + mit_update_delay(&mit_delay, s->mac_reg[RADV] * 4); + } + mit_update_delay(&mit_delay, s->mac_reg[ITR]); + + /* + * According to e1000 SPEC, the Ethernet controller guarantees + * a maximum observable interrupt rate of 7813 interrupts/sec. + * Thus if mit_delay < 500 then the delay should be set to the + * minimum delay possible which is 500. + */ + mit_delay = (mit_delay < 500) ? 500 : mit_delay; + + s->mit_timer_on = 1; + timer_mod(s->mit_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + mit_delay * 256); + s->mit_ide = 0; } s->mit_irq_level = (pending_ints != 0); @@ -1223,9 +1218,6 @@ enum { MAC_ACCESS_PARTIAL = 1, MAC_ACCESS_FLAG_NEEDED = 2 }; * n - flag needed * p - partially implenented */ static const uint8_t mac_reg_access[0x8000] = { - [RDTR] = markflag(MIT), [TADV] = markflag(MIT), - [RADV] = markflag(MIT), [ITR] = markflag(MIT), - [IPAV] = markflag(MAC), [WUC] = markflag(MAC), [IP6AT] = markflag(MAC), [IP4AT] = markflag(MAC), [FFVT] = markflag(MAC), [WUPM] = markflag(MAC), @@ -1394,11 +1386,6 @@ static int e1000_post_load(void *opaque, int version_id) E1000State *s = opaque; NetClientState *nc = qemu_get_queue(s->nic); - if (!chkflag(MIT)) { - s->mac_reg[ITR] = s->mac_reg[RDTR] = s->mac_reg[RADV] = - s->mac_reg[TADV] = 0; - s->mit_irq_level = false; - } s->mit_ide = 0; s->mit_timer_on = true; timer_mod(s->mit_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 1); @@ -1432,13 +1419,6 @@ static int e1000_tx_tso_post_load(void *opaque, int version_id) return 0; } -static bool e1000_mit_state_needed(void *opaque) -{ - E1000State *s = opaque; - - return chkflag(MIT); -} - static bool e1000_full_mac_needed(void *opaque) { E1000State *s = opaque; @@ -1457,7 +1437,6 @@ static const VMStateDescription vmstate_e1000_mit_state = { .name = "e1000/mit_state", .version_id = 1, .minimum_version_id = 1, - .needed = e1000_mit_state_needed, .fields = (VMStateField[]) { VMSTATE_UINT32(mac_reg[RDTR], E1000State), VMSTATE_UINT32(mac_reg[RADV], E1000State), @@ -1699,10 +1678,6 @@ static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp) static Property e1000_properties[] = { DEFINE_NIC_PROPERTIES(E1000State, conf), - DEFINE_PROP_BIT("autonegotiation", E1000State, - compat_flags, E1000_FLAG_AUTONEG_BIT, true), - DEFINE_PROP_BIT("mitigation", E1000State, - compat_flags, E1000_FLAG_MIT_BIT, true), DEFINE_PROP_BIT("extra_mac_registers", E1000State, compat_flags, E1000_FLAG_MAC_BIT, true), DEFINE_PROP_BIT("migrate_tso_props", E1000State, From 946f7c0903c44ad2ace5bb6bf187d66c30548520 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 22 Sep 2023 11:54:02 +0200 Subject: [PATCH 047/208] pc: remove short_root_bus property The property was only used on QEMU 1.6 machine types. Signed-off-by: Paolo Bonzini --- hw/pci-host/i440fx.c | 8 -------- hw/pci-host/q35.c | 7 ------- include/hw/pci-host/q35.h | 1 - 3 files changed, 16 deletions(-) diff --git a/hw/pci-host/i440fx.c b/hw/pci-host/i440fx.c index 62d628768188..653cc3f14950 100644 --- a/hw/pci-host/i440fx.c +++ b/hw/pci-host/i440fx.c @@ -56,7 +56,6 @@ struct I440FXState { uint64_t above_4g_mem_size; uint64_t pci_hole64_size; bool pci_hole64_fix; - uint32_t short_root_bus; char *pci_type; }; @@ -351,19 +350,12 @@ static const TypeInfo i440fx_info = { static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge, PCIBus *rootbus) { - I440FXState *s = I440FX_PCI_HOST_BRIDGE(host_bridge); - - /* For backwards compat with old device paths */ - if (s->short_root_bus) { - return "0000"; - } return "0000:00"; } static Property i440fx_props[] = { DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, I440FXState, pci_hole64_size, I440FX_PCI_HOST_HOLE64_SIZE_DEFAULT), - DEFINE_PROP_UINT32("short_root_bus", I440FXState, short_root_bus, 0), DEFINE_PROP_SIZE(PCI_HOST_BELOW_4G_MEM_SIZE, I440FXState, below_4g_mem_size, 0), DEFINE_PROP_SIZE(PCI_HOST_ABOVE_4G_MEM_SIZE, I440FXState, diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 91c46df9ae31..08534bc7cc09 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -73,12 +73,6 @@ static void q35_host_realize(DeviceState *dev, Error **errp) static const char *q35_host_root_bus_path(PCIHostState *host_bridge, PCIBus *rootbus) { - Q35PCIHost *s = Q35_HOST_DEVICE(host_bridge); - - /* For backwards compat with old device paths */ - if (s->mch.short_root_bus) { - return "0000"; - } return "0000:00"; } @@ -181,7 +175,6 @@ static Property q35_host_props[] = { MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT), DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, Q35PCIHost, mch.pci_hole64_size, Q35_PCI_HOST_HOLE64_SIZE_DEFAULT), - DEFINE_PROP_UINT32("short_root_bus", Q35PCIHost, mch.short_root_bus, 0), DEFINE_PROP_SIZE(PCI_HOST_BELOW_4G_MEM_SIZE, Q35PCIHost, mch.below_4g_mem_size, 0), DEFINE_PROP_SIZE(PCI_HOST_ABOVE_4G_MEM_SIZE, Q35PCIHost, diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h index 1d98bbfe0dd2..bafcbe675214 100644 --- a/include/hw/pci-host/q35.h +++ b/include/hw/pci-host/q35.h @@ -54,7 +54,6 @@ struct MCHPCIState { uint64_t below_4g_mem_size; uint64_t above_4g_mem_size; uint64_t pci_hole64_size; - uint32_t short_root_bus; uint16_t ext_tseg_mbytes; }; From f0df613b98901a2a9184a76f332a853391a73fa8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 26 Sep 2023 12:31:40 +0200 Subject: [PATCH 048/208] make-release: do not ship dtc sources A new enough libfdt is included in all of Debian 11, Ubuntu 20.04 and MSYS2. It has also been included for several minor releases in Fedora and openSUSE Leap, as well as in CentOS. Therefore there is no need anymore to ship the sources together with the QEMU tarballs. Keep the wrap file so that it can be used with --enable-download, but do not ship the sources anymore with either archive-source.sh or make-release. Signed-off-by: Paolo Bonzini --- meson.build | 3 +++ scripts/archive-source.sh | 2 +- scripts/make-release | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 5139db2ff7c8..81430ce2348f 100644 --- a/meson.build +++ b/meson.build @@ -3070,6 +3070,9 @@ if fdt_required.length() > 0 or fdt_opt == 'enabled' endif if fdt_opt in ['enabled', 'auto', 'system'] + if get_option('wrap_mode') == 'nodownload' + fdt_opt = 'system' + endif fdt = cc.find_library('fdt', required: fdt_opt == 'system') if fdt.found() and cc.links(''' #include diff --git a/scripts/archive-source.sh b/scripts/archive-source.sh index 489963049102..65af8063e4bd 100755 --- a/scripts/archive-source.sh +++ b/scripts/archive-source.sh @@ -26,7 +26,7 @@ sub_file="${sub_tdir}/submodule.tar" # independent of what the developer currently has initialized # in their checkout, because the build environment is completely # different to the host OS. -subprojects="dtc keycodemapdb libvfio-user berkeley-softfloat-3 berkeley-testfloat-3" +subprojects="keycodemapdb libvfio-user berkeley-softfloat-3 berkeley-testfloat-3" sub_deinit="" function cleanup() { diff --git a/scripts/make-release b/scripts/make-release index c5db87b3f91b..9c570b87f4a0 100755 --- a/scripts/make-release +++ b/scripts/make-release @@ -17,7 +17,7 @@ if [ $# -ne 2 ]; then fi # Only include wraps that are invoked with subproject() -SUBPROJECTS="dtc libvfio-user keycodemapdb berkeley-softfloat-3 berkeley-testfloat-3" +SUBPROJECTS="libvfio-user keycodemapdb berkeley-softfloat-3 berkeley-testfloat-3" src="$1" version="$2" From 4c545a05abe8859c6e0f64079abe6495fd58d7a8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 27 Sep 2023 15:48:31 +0200 Subject: [PATCH 049/208] meson: clean up static_library keyword arguments These are either built because they are dependencies of other targets, or not needed at all because they are used via extract_objects(). Mark them as "build_by_default: false"; if applicable, mark them as "fa" so that -Wl,--whole-archive does not interact with the linker script used for fuzzing. (The "fa" hack is brittle; updating to Meson 1.1 would allow using declare_dependency(objects: ...) instead). Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1044 Signed-off-by: Paolo Bonzini --- gdbstub/meson.build | 4 ++-- meson.build | 11 +++++++---- tcg/meson.build | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/gdbstub/meson.build b/gdbstub/meson.build index 9500b9dc4e6a..a5a1f4e433f9 100644 --- a/gdbstub/meson.build +++ b/gdbstub/meson.build @@ -21,12 +21,12 @@ libgdb_user = static_library('gdb_user', gdb_user_ss.sources() + genh, name_suffix: 'fa', c_args: '-DCONFIG_USER_ONLY', - build_by_default: have_user) + build_by_default: false) libgdb_softmmu = static_library('gdb_softmmu', gdb_system_ss.sources() + genh, name_suffix: 'fa', - build_by_default: have_system) + build_by_default: false) gdb_user = declare_dependency(link_whole: libgdb_user) user_ss.add(gdb_user) diff --git a/meson.build b/meson.build index 81430ce2348f..21a1bc03f87e 100644 --- a/meson.build +++ b/meson.build @@ -3180,7 +3180,6 @@ foreach d : hx_headers input: files(d[0]), output: d[1], capture: true, - build_by_default: true, # to be removed when added to a target command: [hxtool, '-h', '@INPUT0@']) endforeach genh += hxdep @@ -3366,12 +3365,15 @@ endif qom_ss = qom_ss.apply(config_targetos, strict: false) libqom = static_library('qom', qom_ss.sources() + genh, dependencies: [qom_ss.dependencies()], - name_suffix: 'fa') + name_suffix: 'fa', + build_by_default: false) qom = declare_dependency(link_whole: libqom) event_loop_base = files('event-loop-base.c') -event_loop_base = static_library('event-loop-base', sources: event_loop_base + genh, - build_by_default: true) +event_loop_base = static_library('event-loop-base', + sources: event_loop_base + genh, + name_suffix: 'fa', + build_by_default: false) event_loop_base = declare_dependency(link_whole: event_loop_base, dependencies: [qom]) @@ -3380,6 +3382,7 @@ stub_ss = stub_ss.apply(config_all, strict: false) util_ss.add_all(trace_ss) util_ss = util_ss.apply(config_all, strict: false) libqemuutil = static_library('qemuutil', + build_by_default: false, sources: util_ss.sources() + stub_ss.sources() + genh, dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman]) qemuutil = declare_dependency(link_with: libqemuutil, diff --git a/tcg/meson.build b/tcg/meson.build index 0014dca7d4fa..4be4a616caa0 100644 --- a/tcg/meson.build +++ b/tcg/meson.build @@ -28,7 +28,7 @@ libtcg_user = static_library('tcg_user', tcg_ss.sources() + genh, name_suffix: 'fa', c_args: '-DCONFIG_USER_ONLY', - build_by_default: have_user) + build_by_default: false) tcg_user = declare_dependency(link_with: libtcg_user, dependencies: tcg_ss.dependencies()) @@ -38,7 +38,7 @@ libtcg_softmmu = static_library('tcg_softmmu', tcg_ss.sources() + genh, name_suffix: 'fa', c_args: '-DCONFIG_SOFTMMU', - build_by_default: have_system) + build_by_default: false) tcg_softmmu = declare_dependency(link_with: libtcg_softmmu, dependencies: tcg_ss.dependencies()) From 9a239c6eae68e0bfb989f9ebb2907e04f98fde99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:13 +0200 Subject: [PATCH 050/208] tcg: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: tcg/tcg.c:2551:27: error: declaration shadows a local variable [-Werror,-Wshadow] MemOp op = get_memop(oi); ^ tcg/tcg.c:2437:12: note: previous declaration is here TCGOp *op; ^ accel/tcg/tb-maint.c:245:18: error: declaration shadows a local variable [-Werror,-Wshadow] for (int i = 0; i < V_L2_SIZE; i++) { ^ accel/tcg/tb-maint.c:210:9: note: previous declaration is here int i; ^ Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-2-philmd@linaro.org> Signed-off-by: Markus Armbruster --- accel/tcg/tb-maint.c | 3 +-- tcg/tcg.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c index 32ae8af61cdf..8c71cebabddb 100644 --- a/accel/tcg/tb-maint.c +++ b/accel/tcg/tb-maint.c @@ -207,13 +207,12 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, bool alloc) { PageDesc *pd; void **lp; - int i; /* Level 1. Always allocated. */ lp = l1_map + ((index >> v_l1_shift) & (v_l1_size - 1)); /* Level 2..N-1. */ - for (i = v_l2_levels; i > 0; i--) { + for (int i = v_l2_levels; i > 0; i--) { void **p = qatomic_rcu_read(lp); if (p == NULL) { diff --git a/tcg/tcg.c b/tcg/tcg.c index 604fa9bf3e83..ea94d0fbff44 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2549,21 +2549,21 @@ static void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs) { const char *s_al, *s_op, *s_at; MemOpIdx oi = op->args[k++]; - MemOp op = get_memop(oi); + MemOp mop = get_memop(oi); unsigned ix = get_mmuidx(oi); - s_al = alignment_name[(op & MO_AMASK) >> MO_ASHIFT]; - s_op = ldst_name[op & (MO_BSWAP | MO_SSIZE)]; - s_at = atom_name[(op & MO_ATOM_MASK) >> MO_ATOM_SHIFT]; - op &= ~(MO_AMASK | MO_BSWAP | MO_SSIZE | MO_ATOM_MASK); + s_al = alignment_name[(mop & MO_AMASK) >> MO_ASHIFT]; + s_op = ldst_name[mop & (MO_BSWAP | MO_SSIZE)]; + s_at = atom_name[(mop & MO_ATOM_MASK) >> MO_ATOM_SHIFT]; + mop &= ~(MO_AMASK | MO_BSWAP | MO_SSIZE | MO_ATOM_MASK); /* If all fields are accounted for, print symbolically. */ - if (!op && s_al && s_op && s_at) { + if (!mop && s_al && s_op && s_at) { col += ne_fprintf(f, ",%s%s%s,%u", s_at, s_al, s_op, ix); } else { - op = get_memop(oi); - col += ne_fprintf(f, ",$0x%x,%u", op, ix); + mop = get_memop(oi); + col += ne_fprintf(f, ",$0x%x,%u", mop, ix); } i = 1; } From d54deb2a0723d696bc4e95265d6ccb4236cb0cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:14 +0200 Subject: [PATCH 051/208] target/arm/tcg: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: target/arm/tcg/translate-m-nocp.c: In function ‘gen_M_fp_sysreg_read’: target/arm/tcg/translate-m-nocp.c:509:18: warning: declaration of ‘tmp’ shadows a previous local [-Wshadow=compatible-local] 509 | TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]); | ^~~ target/arm/tcg/translate-m-nocp.c:433:14: note: shadowed declaration is here 433 | TCGv_i32 tmp; | ^~~ --- target/arm/tcg/mve_helper.c: In function ‘helper_mve_vqshlsb’: target/arm/tcg/mve_helper.c:1259:19: warning: declaration of ‘r’ shadows a previous local [-Wshadow=compatible-local] 1259 | typeof(N) r = FN(N, (int8_t)(M), sizeof(N) * 8, ROUND, &su32); \ | ^ target/arm/tcg/mve_helper.c:1267:5: note: in expansion of macro ‘WRAP_QRSHL_HELPER’ 1267 | WRAP_QRSHL_HELPER(do_sqrshl_bhs, N, M, false, satp) | ^~~~~~~~~~~~~~~~~ target/arm/tcg/mve_helper.c:927:22: note: in expansion of macro ‘DO_SQSHL_OP’ 927 | TYPE r = FN(n[H##ESIZE(e)], m[H##ESIZE(e)], &sat); \ | ^~ target/arm/tcg/mve_helper.c:945:5: note: in expansion of macro ‘DO_2OP_SAT’ 945 | DO_2OP_SAT(OP##b, 1, int8_t, FN) \ | ^~~~~~~~~~ target/arm/tcg/mve_helper.c:1277:1: note: in expansion of macro ‘DO_2OP_SAT_S’ 1277 | DO_2OP_SAT_S(vqshls, DO_SQSHL_OP) | ^~~~~~~~~~~~ --- target/arm/tcg/mve_helper.c: In function ‘do_sqrshl48_d’: target/arm/tcg/mve_helper.c:2463:17: warning: declaration of ‘extval’ shadows a previous local [-Wshadow=compatible-local] 2463 | int64_t extval = sextract64(src << shift, 0, 48); | ^~~~~~ target/arm/tcg/mve_helper.c:2443:18: note: shadowed declaration is here 2443 | int64_t val, extval; | ^~~~~~ --- target/arm/tcg/mve_helper.c: In function ‘do_uqrshl48_d’: target/arm/tcg/mve_helper.c:2495:18: warning: declaration of ‘extval’ shadows a previous local [-Wshadow=compatible-local] 2495 | uint64_t extval = extract64(src << shift, 0, 48); | ^~~~~~ target/arm/tcg/mve_helper.c:2479:19: note: shadowed declaration is here 2479 | uint64_t val, extval; | ^~~~~~ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-3-philmd@linaro.org> Reviewed-by: Peter Maydell Signed-off-by: Markus Armbruster --- target/arm/tcg/mve_helper.c | 16 ++++++++-------- target/arm/tcg/translate-m-nocp.c | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/target/arm/tcg/mve_helper.c b/target/arm/tcg/mve_helper.c index c666a96ba17d..8b99736aad1e 100644 --- a/target/arm/tcg/mve_helper.c +++ b/target/arm/tcg/mve_helper.c @@ -925,8 +925,8 @@ DO_1OP_IMM(vorri, DO_ORRI) bool qc = false; \ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \ bool sat = false; \ - TYPE r = FN(n[H##ESIZE(e)], m[H##ESIZE(e)], &sat); \ - mergemask(&d[H##ESIZE(e)], r, mask); \ + TYPE r_ = FN(n[H##ESIZE(e)], m[H##ESIZE(e)], &sat); \ + mergemask(&d[H##ESIZE(e)], r_, mask); \ qc |= sat & mask & 1; \ } \ if (qc) { \ @@ -1250,11 +1250,11 @@ DO_2OP_SAT(vqsubsw, 4, int32_t, DO_SQSUB_W) #define WRAP_QRSHL_HELPER(FN, N, M, ROUND, satp) \ ({ \ uint32_t su32 = 0; \ - typeof(N) r = FN(N, (int8_t)(M), sizeof(N) * 8, ROUND, &su32); \ + typeof(N) qrshl_ret = FN(N, (int8_t)(M), sizeof(N) * 8, ROUND, &su32); \ if (su32) { \ *satp = true; \ } \ - r; \ + qrshl_ret; \ }) #define DO_SQSHL_OP(N, M, satp) \ @@ -1292,12 +1292,12 @@ DO_2OP_SAT_U(vqrshlu, DO_UQRSHL_OP) for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \ bool sat = false; \ if ((e & 1) == XCHG) { \ - TYPE r = FN(n[H##ESIZE(e)], \ + TYPE vqdmladh_ret = FN(n[H##ESIZE(e)], \ m[H##ESIZE(e - XCHG)], \ n[H##ESIZE(e + (1 - 2 * XCHG))], \ m[H##ESIZE(e + (1 - XCHG))], \ ROUND, &sat); \ - mergemask(&d[H##ESIZE(e)], r, mask); \ + mergemask(&d[H##ESIZE(e)], vqdmladh_ret, mask); \ qc |= sat & mask & 1; \ } \ } \ @@ -2454,7 +2454,7 @@ static inline int64_t do_sqrshl48_d(int64_t src, int64_t shift, return extval; } } else if (shift < 48) { - int64_t extval = sextract64(src << shift, 0, 48); + extval = sextract64(src << shift, 0, 48); if (!sat || src == (extval >> shift)) { return extval; } @@ -2486,7 +2486,7 @@ static inline uint64_t do_uqrshl48_d(uint64_t src, int64_t shift, return extval; } } else if (shift < 48) { - uint64_t extval = extract64(src << shift, 0, 48); + extval = extract64(src << shift, 0, 48); if (!sat || src == (extval >> shift)) { return extval; } diff --git a/target/arm/tcg/translate-m-nocp.c b/target/arm/tcg/translate-m-nocp.c index 33f6478bb9f2..42308c4db5d5 100644 --- a/target/arm/tcg/translate-m-nocp.c +++ b/target/arm/tcg/translate-m-nocp.c @@ -506,7 +506,7 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno, gen_branch_fpInactive(s, TCG_COND_EQ, lab_active); /* fpInactive case: reads as FPDSCR_NS */ - TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]); + tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]); storefn(s, opaque, tmp, true); lab_end = gen_new_label(); tcg_gen_br(lab_end); From 5a3d2c3562a9b35443fb4121ba6efff9d6cdbb91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:15 +0200 Subject: [PATCH 052/208] target/arm/hvf: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Peter Maydell analysis [*]: The hvf_vcpu_exec() function is not documented, but in practice its caller expects it to return either EXCP_DEBUG (for "this was a guest debug exception you need to deal with") or something else (presumably the intention being 0 for OK). The hvf_sysreg_read() and hvf_sysreg_write() functions are also not documented, but they return 0 on success, or 1 for a completely unrecognized sysreg where we've raised the UNDEF exception (but not if we raised an UNDEF exception for an unrecognized GIC sysreg -- I think this is a bug). We use this return value to decide whether we need to advance the PC past the insn or not. It's not the same as the return value we want to return from hvf_vcpu_exec(). Retain the variable as locally scoped but give it a name that doesn't clash with the other function-scoped variable. This fixes: target/arm/hvf/hvf.c:1936:13: error: declaration shadows a local variable [-Werror,-Wshadow] int ret = 0; ^ target/arm/hvf/hvf.c:1807:9: note: previous declaration is here int ret; ^ [*] https://lore.kernel.org/qemu-devel/CAFEAcA_e+fU6JKtS+W63wr9cCJ6btu_hT_ydZWOwC0kBkDYYYQ@mail.gmail.com/ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-4-philmd@linaro.org> Reviewed-by: Peter Maydell Signed-off-by: Markus Armbruster --- target/arm/hvf/hvf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 546c0e817f4d..757e13b0f904 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -1934,16 +1934,16 @@ int hvf_vcpu_exec(CPUState *cpu) uint32_t rt = (syndrome >> 5) & 0x1f; uint32_t reg = syndrome & SYSREG_MASK; uint64_t val; - int ret = 0; + int sysreg_ret = 0; if (isread) { - ret = hvf_sysreg_read(cpu, reg, rt); + sysreg_ret = hvf_sysreg_read(cpu, reg, rt); } else { val = hvf_get_reg(cpu, rt); - ret = hvf_sysreg_write(cpu, reg, val); + sysreg_ret = hvf_sysreg_write(cpu, reg, val); } - advance_pc = !ret; + advance_pc = !sysreg_ret; break; } case EC_WFX_TRAP: From 92e0ef7d907a7b39d942732a29c04446a4ef5cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:16 +0200 Subject: [PATCH 053/208] target/mips: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: target/mips/tcg/nanomips_translate.c.inc:4410:33: error: declaration shadows a local variable [-Werror,-Wshadow] int32_t imm = extract32(ctx->opcode, 1, 13) | ^ target/mips/tcg/nanomips_translate.c.inc:3577:9: note: previous declaration is here int imm; ^ target/mips/tcg/translate.c:15578:19: error: declaration shadows a local variable [-Werror,-Wshadow] for (unsigned i = 1; i < 32; i++) { ^ target/mips/tcg/translate.c:15567:9: note: previous declaration is here int i; ^ target/mips/tcg/msa_helper.c:7478:13: error: declaration shadows a local variable [-Werror,-Wshadow] MSA_FLOAT_MAXOP(pwx->w[0], min, pws->w[0], pws->w[0], 32); ^ target/mips/tcg/msa_helper.c:7434:23: note: expanded from macro 'MSA_FLOAT_MAXOP' float_status *status = &env->active_tc.msa_fp_status; ^ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-5-philmd@linaro.org> Signed-off-by: Markus Armbruster --- target/mips/tcg/msa_helper.c | 8 ++++---- target/mips/tcg/nanomips_translate.c.inc | 6 +++--- target/mips/tcg/translate.c | 8 +++----- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/target/mips/tcg/msa_helper.c b/target/mips/tcg/msa_helper.c index c314a74397ff..7a8dbada5d96 100644 --- a/target/mips/tcg/msa_helper.c +++ b/target/mips/tcg/msa_helper.c @@ -7432,15 +7432,15 @@ void helper_msa_ftq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, #define MSA_FLOAT_MAXOP(DEST, OP, ARG1, ARG2, BITS) \ do { \ - float_status *status = &env->active_tc.msa_fp_status; \ + float_status *status_ = &env->active_tc.msa_fp_status; \ int c; \ \ - set_float_exception_flags(0, status); \ - DEST = float ## BITS ## _ ## OP(ARG1, ARG2, status); \ + set_float_exception_flags(0, status_); \ + DEST = float ## BITS ## _ ## OP(ARG1, ARG2, status_); \ c = update_msacsr(env, 0, 0); \ \ if (get_enabled_exceptions(env, c)) { \ - DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \ + DEST = ((FLOAT_SNAN ## BITS(status_) >> 6) << 6) | c; \ } \ } while (0) diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc index a98dde0d2e10..d81a7c2d1116 100644 --- a/target/mips/tcg/nanomips_translate.c.inc +++ b/target/mips/tcg/nanomips_translate.c.inc @@ -4407,8 +4407,8 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) case NM_BPOSGE32C: check_dsp_r3(ctx); { - int32_t imm = extract32(ctx->opcode, 1, 13) | - extract32(ctx->opcode, 0, 1) << 13; + imm = extract32(ctx->opcode, 1, 13) + | extract32(ctx->opcode, 0, 1) << 13; gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2, imm << 1); @@ -4635,7 +4635,7 @@ static int decode_isa_nanomips(CPUMIPSState *env, DisasContext *ctx) break; case NM_LI16: { - int imm = extract32(ctx->opcode, 0, 7); + imm = extract32(ctx->opcode, 0, 7); imm = (imm == 0x7f ? -1 : imm); if (rt != 0) { tcg_gen_movi_tl(cpu_gpr[rt], imm); diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 9bb40f1849d6..26d741d96055 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -15564,10 +15564,8 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns, void mips_tcg_init(void) { - int i; - cpu_gpr[0] = NULL; - for (i = 1; i < 32; i++) + for (unsigned i = 1; i < 32; i++) cpu_gpr[i] = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, active_tc.gpr[i]), @@ -15584,7 +15582,7 @@ void mips_tcg_init(void) rname); } #endif /* !TARGET_MIPS64 */ - for (i = 0; i < 32; i++) { + for (unsigned i = 0; i < 32; i++) { int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]); fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]); @@ -15592,7 +15590,7 @@ void mips_tcg_init(void) msa_translate_init(); cpu_PC = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, active_tc.PC), "PC"); - for (i = 0; i < MIPS_DSP_ACC; i++) { + for (unsigned i = 0; i < MIPS_DSP_ACC; i++) { cpu_HI[i] = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, active_tc.HI[i]), regnames_HI[i]); From 574d57254596d328d1a3c419e138e69369f2a98b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:17 +0200 Subject: [PATCH 054/208] target/m68k: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: target/m68k/translate.c:828:18: error: declaration shadows a local variable [-Werror,-Wshadow] TCGv tmp = tcg_temp_new(); ^ target/m68k/translate.c:801:15: note: previous declaration is here TCGv reg, tmp, result; ^ Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell Message-ID: <20230904161235.84651-6-philmd@linaro.org> Signed-off-by: Markus Armbruster --- target/m68k/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 9e224fe7965c..15c9ddf42732 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -824,7 +824,7 @@ static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0, reg = get_areg(s, reg0); result = gen_ldst(s, opsize, reg, val, what, index); if (what == EA_STORE || !addrp) { - TCGv tmp = tcg_temp_new(); + tmp = tcg_temp_new(); if (reg0 == 7 && opsize == OS_BYTE && m68k_feature(s->env, M68K_FEATURE_M68K)) { tcg_gen_addi_i32(tmp, reg, 2); From 81b8056a41eabff08e243c80b628fc18bfac2b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:18 +0200 Subject: [PATCH 055/208] target/tricore: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: target/tricore/translate.c:5016:18: warning: declaration of ‘temp’ shadows a previous local [-Wshadow=compatible-local] 5016 | TCGv temp = tcg_constant_i32(const9); | ^~~~ target/tricore/translate.c:4958:10: note: shadowed declaration is here 4958 | TCGv temp; | ^~~~ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-7-philmd@linaro.org> Reviewed-by: Bastian Koppelmann Signed-off-by: Markus Armbruster --- target/tricore/translate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/tricore/translate.c b/target/tricore/translate.c index 6ae5ccbf726d..9ca211b2a8b4 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -4962,8 +4962,6 @@ static void decode_rc_logical_shift(DisasContext *ctx) const9 = MASK_OP_RC_CONST9(ctx->opcode); op2 = MASK_OP_RC_OP2(ctx->opcode); - temp = tcg_temp_new(); - switch (op2) { case OPC2_32_RC_AND: tcg_gen_andi_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], const9); @@ -4972,10 +4970,12 @@ static void decode_rc_logical_shift(DisasContext *ctx) tcg_gen_andi_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], ~const9); break; case OPC2_32_RC_NAND: + temp = tcg_temp_new(); tcg_gen_movi_tl(temp, const9); tcg_gen_nand_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], temp); break; case OPC2_32_RC_NOR: + temp = tcg_temp_new(); tcg_gen_movi_tl(temp, const9); tcg_gen_nor_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], temp); break; @@ -5013,7 +5013,7 @@ static void decode_rc_logical_shift(DisasContext *ctx) break; case OPC2_32_RC_SHUFFLE: if (has_feature(ctx, TRICORE_FEATURE_162)) { - TCGv temp = tcg_constant_i32(const9); + temp = tcg_constant_i32(const9); gen_helper_shuffle(cpu_gpr_d[r2], cpu_gpr_d[r1], temp); } else { generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); From 807e4d1d2155b7cf4d18bf4e0a73c4e7023f0d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:19 +0200 Subject: [PATCH 056/208] hw/arm/armv7m: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: hw/arm/armv7m.c: In function ‘armv7m_realize’: hw/arm/armv7m.c:520:27: warning: declaration of ‘sbd’ shadows a previous local [-Wshadow=compatible-local] 520 | SysBusDevice *sbd = SYS_BUS_DEVICE(&s->bitband[i]); | ^~~ hw/arm/armv7m.c:278:19: note: shadowed declaration is here 278 | SysBusDevice *sbd; | ^~~ --- hw/arm/armsse.c: In function ‘armsse_realize’: hw/arm/armsse.c:1471:27: warning: declaration of ‘mr’ shadows a previous local [-Wshadow=compatible-local] 1471 | MemoryRegion *mr; | ^~ hw/arm/armsse.c:917:19: note: shadowed declaration is here 917 | MemoryRegion *mr; | ^~ --- hw/arm/armsse.c:1608:22: warning: declaration of ‘dev_splitter’ shadows a previous local [-Wshadow=compatible-local] 1608 | DeviceState *dev_splitter = DEVICE(splitter); | ^~~~~~~~~~~~ hw/arm/armsse.c:923:18: note: shadowed declaration is here 923 | DeviceState *dev_splitter; | ^~~~~~~~~~~~ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-8-philmd@linaro.org> Reviewed-by: Peter Maydell Signed-off-by: Markus Armbruster --- hw/arm/armsse.c | 16 ++++++---------- hw/arm/armv7m.c | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c index 11cd08b6c1e6..31acbf73471d 100644 --- a/hw/arm/armsse.c +++ b/hw/arm/armsse.c @@ -1468,7 +1468,6 @@ static void armsse_realize(DeviceState *dev, Error **errp) if (info->has_cachectrl) { for (i = 0; i < info->num_cpus; i++) { char *name = g_strdup_printf("cachectrl%d", i); - MemoryRegion *mr; qdev_prop_set_string(DEVICE(&s->cachectrl[i]), "name", name); g_free(name); @@ -1484,7 +1483,6 @@ static void armsse_realize(DeviceState *dev, Error **errp) if (info->has_cpusecctrl) { for (i = 0; i < info->num_cpus; i++) { char *name = g_strdup_printf("CPUSECCTRL%d", i); - MemoryRegion *mr; qdev_prop_set_string(DEVICE(&s->cpusecctrl[i]), "name", name); g_free(name); @@ -1499,7 +1497,6 @@ static void armsse_realize(DeviceState *dev, Error **errp) } if (info->has_cpuid) { for (i = 0; i < info->num_cpus; i++) { - MemoryRegion *mr; qdev_prop_set_uint32(DEVICE(&s->cpuid[i]), "CPUID", i); if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpuid[i]), errp)) { @@ -1512,7 +1509,6 @@ static void armsse_realize(DeviceState *dev, Error **errp) } if (info->has_cpu_pwrctrl) { for (i = 0; i < info->num_cpus; i++) { - MemoryRegion *mr; if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpu_pwrctrl[i]), errp)) { return; @@ -1605,7 +1601,7 @@ static void armsse_realize(DeviceState *dev, Error **errp) /* Wire up the splitters for the MPC IRQs */ for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) { SplitIRQ *splitter = &s->mpc_irq_splitter[i]; - DeviceState *dev_splitter = DEVICE(splitter); + DeviceState *devs = DEVICE(splitter); if (!object_property_set_int(OBJECT(splitter), "num-lines", 2, errp)) { @@ -1617,22 +1613,22 @@ static void armsse_realize(DeviceState *dev, Error **errp) if (i < IOTS_NUM_EXP_MPC) { /* Splitter input is from GPIO input line */ - s->mpcexp_status_in[i] = qdev_get_gpio_in(dev_splitter, 0); - qdev_connect_gpio_out(dev_splitter, 0, + s->mpcexp_status_in[i] = qdev_get_gpio_in(devs, 0); + qdev_connect_gpio_out(devs, 0, qdev_get_gpio_in_named(dev_secctl, "mpcexp_status", i)); } else { /* Splitter input is from our own MPC */ qdev_connect_gpio_out_named(DEVICE(&s->mpc[i - IOTS_NUM_EXP_MPC]), "irq", 0, - qdev_get_gpio_in(dev_splitter, 0)); - qdev_connect_gpio_out(dev_splitter, 0, + qdev_get_gpio_in(devs, 0)); + qdev_connect_gpio_out(devs, 0, qdev_get_gpio_in_named(dev_secctl, "mpc_status", i - IOTS_NUM_EXP_MPC)); } - qdev_connect_gpio_out(dev_splitter, 1, + qdev_connect_gpio_out(devs, 1, qdev_get_gpio_in(DEVICE(&s->mpc_irq_orgate), i)); } /* Create GPIO inputs which will pass the line state for our diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index bf173b10b8b8..1f78e18872f6 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -517,7 +517,7 @@ static void armv7m_realize(DeviceState *dev, Error **errp) for (i = 0; i < ARRAY_SIZE(s->bitband); i++) { if (s->enable_bitband) { Object *obj = OBJECT(&s->bitband[i]); - SysBusDevice *sbd = SYS_BUS_DEVICE(&s->bitband[i]); + sbd = SYS_BUS_DEVICE(&s->bitband[i]); if (!object_property_set_int(obj, "base", bitband_input_addr[i], errp)) { From c7f14e4898bb4fcaa1420434bf4331e2843946fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:20 +0200 Subject: [PATCH 057/208] hw/arm/virt: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: hw/arm/virt.c:821:22: error: declaration shadows a local variable [-Werror,-Wshadow] qemu_irq irq = qdev_get_gpio_in(vms->gic, ^ hw/arm/virt.c:803:13: note: previous declaration is here int irq; ^ Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell Message-ID: <20230904161235.84651-9-philmd@linaro.org> Signed-off-by: Markus Armbruster --- hw/arm/virt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 8ad78b23c242..15e74249f9d8 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -801,7 +801,6 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) for (i = 0; i < smp_cpus; i++) { DeviceState *cpudev = DEVICE(qemu_get_cpu(i)); int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS; - int irq; /* Mapping from the output timer irq lines from the CPU to the * GIC PPI inputs we use for the virt board. */ @@ -812,7 +811,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ, }; - for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) { + for (unsigned irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) { qdev_connect_gpio_out(cpudev, irq, qdev_get_gpio_in(vms->gic, ppibase + timer_irq[irq])); From 2f6037a2359fb653704ff240fb552bd77537f9ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:21 +0200 Subject: [PATCH 058/208] hw/arm/allwinner: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: hw/arm/allwinner-r40.c:412:14: error: declaration shadows a local variable [-Werror,-Wshadow] for (int i = 0; i < AW_R40_NUM_MMCS; i++) { ^ hw/arm/allwinner-r40.c:299:14: note: previous declaration is here unsigned i; ^ Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell Message-ID: <20230904161235.84651-10-philmd@linaro.org> Signed-off-by: Markus Armbruster --- hw/arm/allwinner-r40.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c index 7d29eb224f67..a0d367c60d17 100644 --- a/hw/arm/allwinner-r40.c +++ b/hw/arm/allwinner-r40.c @@ -296,10 +296,9 @@ static void allwinner_r40_realize(DeviceState *dev, Error **errp) { const char *r40_nic_models[] = { "gmac", "emac", NULL }; AwR40State *s = AW_R40(dev); - unsigned i; /* CPUs */ - for (i = 0; i < AW_R40_NUM_CPUS; i++) { + for (unsigned i = 0; i < AW_R40_NUM_CPUS; i++) { /* * Disable secondary CPUs. Guest EL3 firmware will start @@ -335,7 +334,7 @@ static void allwinner_r40_realize(DeviceState *dev, Error **errp) * maintenance interrupt signal to the appropriate GIC PPI inputs, * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs. */ - for (i = 0; i < AW_R40_NUM_CPUS; i++) { + for (unsigned i = 0; i < AW_R40_NUM_CPUS; i++) { DeviceState *cpudev = DEVICE(&s->cpus[i]); int ppibase = AW_R40_GIC_NUM_SPI + i * GIC_INTERNAL + GIC_NR_SGIS; int irq; @@ -494,7 +493,7 @@ static void allwinner_r40_realize(DeviceState *dev, Error **errp) qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_EMAC)); /* Unimplemented devices */ - for (i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) { + for (unsigned i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) { create_unimplemented_device(r40_unimplemented[i].device_name, r40_unimplemented[i].base, r40_unimplemented[i].size); From 5f87dddbc2aaa126a6c1334115a5ec9bd33fb62a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:24 +0200 Subject: [PATCH 059/208] hw/m68k: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: hw/m68k/virt.c:263:13: error: declaration shadows a local variable [-Werror,-Wshadow] BOOTINFOSTR(param_ptr, BI_COMMAND_LINE, ^ hw/m68k/bootinfo.h:47:13: note: expanded from macro 'BOOTINFOSTR' int i; \ ^ hw/m68k/virt.c:130:9: note: previous declaration is here int i; ^ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-13-philmd@linaro.org> Reviewed-by: Thomas Huth Signed-off-by: Markus Armbruster --- hw/m68k/bootinfo.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/hw/m68k/bootinfo.h b/hw/m68k/bootinfo.h index a3d37e3c8094..0e6e3eea87d7 100644 --- a/hw/m68k/bootinfo.h +++ b/hw/m68k/bootinfo.h @@ -44,15 +44,14 @@ #define BOOTINFOSTR(base, id, string) \ do { \ - int i; \ stw_p(base, id); \ base += 2; \ stw_p(base, \ (sizeof(struct bi_record) + strlen(string) + \ 1 /* null termination */ + 3 /* padding */) & ~3); \ base += 2; \ - for (i = 0; string[i]; i++) { \ - stb_p(base++, string[i]); \ + for (unsigned i_ = 0; string[i_]; i_++) { \ + stb_p(base++, string[i_]); \ } \ stb_p(base++, 0); \ base = QEMU_ALIGN_PTR_UP(base, 4); \ @@ -60,7 +59,6 @@ #define BOOTINFODATA(base, id, data, len) \ do { \ - int i; \ stw_p(base, id); \ base += 2; \ stw_p(base, \ @@ -69,8 +67,8 @@ base += 2; \ stw_p(base, len); \ base += 2; \ - for (i = 0; i < len; ++i) { \ - stb_p(base++, data[i]); \ + for (unsigned i_ = 0; i_ < len; ++i_) { \ + stb_p(base++, data[i_]); \ } \ base = QEMU_ALIGN_PTR_UP(base, 4); \ } while (0) From 4705c8e5a2d0e62a276ce21e6b15bff0e7e42bdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:25 +0200 Subject: [PATCH 060/208] hw/microblaze: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: hw/microblaze/petalogix_ml605_mmu.c: In function ‘petalogix_ml605_init’: hw/microblaze/petalogix_ml605_mmu.c:186:24: warning: declaration of ‘dinfo’ shadows a previous local [-Wshadow=compatible-local] 186 | DriveInfo *dinfo = drive_get(IF_MTD, 0, i); | ^~~~~ hw/microblaze/petalogix_ml605_mmu.c:78:16: note: shadowed declaration is here 78 | DriveInfo *dinfo; | ^~~~~ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-14-philmd@linaro.org> Signed-off-by: Markus Armbruster --- hw/microblaze/petalogix_ml605_mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c index ea0fb68cf026..fb7889cf67c6 100644 --- a/hw/microblaze/petalogix_ml605_mmu.c +++ b/hw/microblaze/petalogix_ml605_mmu.c @@ -183,7 +183,7 @@ petalogix_ml605_init(MachineState *machine) spi = (SSIBus *)qdev_get_child_bus(dev, "spi"); for (i = 0; i < NUM_SPI_FLASHES; i++) { - DriveInfo *dinfo = drive_get(IF_MTD, 0, i); + dinfo = drive_get(IF_MTD, 0, i); qemu_irq cs_line; dev = qdev_new("n25q128"); From 09e24b10de02b19d193d85645c19a68b98263bef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:26 +0200 Subject: [PATCH 061/208] hw/nios2: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: hw/nios2/10m50_devboard.c: In function ‘nios2_10m50_ghrd_init’: hw/nios2/10m50_devboard.c:101:22: warning: declaration of ‘dev’ shadows a previous local [-Wshadow=compatible-local] 101 | DeviceState *dev = qdev_new(TYPE_NIOS2_VIC); | ^~~ hw/nios2/10m50_devboard.c:60:18: note: shadowed declaration is here 60 | DeviceState *dev; | ^~~ hw/nios2/10m50_devboard.c:110:18: warning: declaration of ‘i’ shadows a previous local [-Wshadow=compatible-local] 110 | for (int i = 0; i < 32; i++) { | ^ hw/nios2/10m50_devboard.c:67:9: note: shadowed declaration is here 67 | int i; | ^ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-15-philmd@linaro.org> Signed-off-by: Markus Armbruster --- hw/nios2/10m50_devboard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/nios2/10m50_devboard.c b/hw/nios2/10m50_devboard.c index 91383fb09791..952a0dc33e39 100644 --- a/hw/nios2/10m50_devboard.c +++ b/hw/nios2/10m50_devboard.c @@ -98,7 +98,7 @@ static void nios2_10m50_ghrd_init(MachineState *machine) qdev_realize_and_unref(DEVICE(cpu), NULL, &error_fatal); if (nms->vic) { - DeviceState *dev = qdev_new(TYPE_NIOS2_VIC); + dev = qdev_new(TYPE_NIOS2_VIC); MemoryRegion *dev_mr; qemu_irq cpu_irq; @@ -107,7 +107,7 @@ static void nios2_10m50_ghrd_init(MachineState *machine) cpu_irq = qdev_get_gpio_in_named(DEVICE(cpu), "EIC", 0); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq); - for (int i = 0; i < 32; i++) { + for (i = 0; i < 32; i++) { irq[i] = qdev_get_gpio_in(dev, i); } From 1728593a82cdd8ffcd2a5a759fb301c71ae4c251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:27 +0200 Subject: [PATCH 062/208] net/eth: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: net/eth.c:435:20: error: declaration shadows a local variable [-Werror,-Wshadow] size_t input_size = iov_size(pkt, pkt_frags); ^ net/eth.c:413:16: note: previous declaration is here size_t input_size = iov_size(pkt, pkt_frags); ^ Suggested-by: Akihiko Odaki Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-16-philmd@linaro.org> Reviewed-by: Eric Blake Reviewed-by: Akihiko Odaki Signed-off-by: Markus Armbruster --- net/eth.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/eth.c b/net/eth.c index 649e66bb1fe2..3f680cc033a3 100644 --- a/net/eth.c +++ b/net/eth.c @@ -432,8 +432,6 @@ _eth_get_rss_ex_src_addr(const struct iovec *pkt, int pkt_frags, } if (opthdr.type == IP6_OPT_HOME) { - size_t input_size = iov_size(pkt, pkt_frags); - if (input_size < opt_offset + sizeof(opthdr)) { return false; } From 5f6d4f79af6eb4b0eed9cb3272073841514ca989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:28 +0200 Subject: [PATCH 063/208] crypto/cipher-gnutls.c: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: In file included from crypto/cipher.c:140: crypto/cipher-gnutls.c.inc: In function ‘qcrypto_gnutls_cipher_encrypt’: crypto/cipher-gnutls.c.inc:116:17: warning: declaration of ‘err’ shadows a previous local [-Wshadow=compatible-local] 116 | int err = gnutls_cipher_init(&handle, ctx->galg, &gkey, NULL); | ^~~ crypto/cipher-gnutls.c.inc:94:9: note: shadowed declaration is here 94 | int err; | ^~~ --- crypto/cipher-gnutls.c.inc: In function ‘qcrypto_gnutls_cipher_decrypt’: crypto/cipher-gnutls.c.inc:177:17: warning: declaration of ‘err’ shadows a previous local [-Wshadow=compatible-local] 177 | int err = gnutls_cipher_init(&handle, ctx->galg, &gkey, NULL); | ^~~ crypto/cipher-gnutls.c.inc:154:9: note: shadowed declaration is here 154 | int err; | ^~~ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-17-philmd@linaro.org> Reviewed-by: Daniel P. Berrangé Signed-off-by: Markus Armbruster --- crypto/cipher-gnutls.c.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/cipher-gnutls.c.inc b/crypto/cipher-gnutls.c.inc index 501e4e07a5b0..d3e231c13c92 100644 --- a/crypto/cipher-gnutls.c.inc +++ b/crypto/cipher-gnutls.c.inc @@ -113,7 +113,7 @@ qcrypto_gnutls_cipher_encrypt(QCryptoCipher *cipher, while (len) { gnutls_cipher_hd_t handle; gnutls_datum_t gkey = { (unsigned char *)ctx->key, ctx->nkey }; - int err = gnutls_cipher_init(&handle, ctx->galg, &gkey, NULL); + err = gnutls_cipher_init(&handle, ctx->galg, &gkey, NULL); if (err != 0) { error_setg(errp, "Cannot initialize cipher: %s", gnutls_strerror(err)); @@ -174,7 +174,7 @@ qcrypto_gnutls_cipher_decrypt(QCryptoCipher *cipher, while (len) { gnutls_cipher_hd_t handle; gnutls_datum_t gkey = { (unsigned char *)ctx->key, ctx->nkey }; - int err = gnutls_cipher_init(&handle, ctx->galg, &gkey, NULL); + err = gnutls_cipher_init(&handle, ctx->galg, &gkey, NULL); if (err != 0) { error_setg(errp, "Cannot initialize cipher: %s", gnutls_strerror(err)); From fbf58f2141f670c1e4fc63be36e8a45330ab1e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:29 +0200 Subject: [PATCH 064/208] util/vhost-user-server: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: util/vhost-user-server.c: In function ‘set_watch’: util/vhost-user-server.c:274:20: warning: declaration of ‘vu_fd_watch’ shadows a previous local [-Wshadow=compatible-local] 274 | VuFdWatch *vu_fd_watch = g_new0(VuFdWatch, 1); | ^~~~~~~~~~~ util/vhost-user-server.c:271:16: note: shadowed declaration is here 271 | VuFdWatch *vu_fd_watch = find_vu_fd_watch(server, fd); | ^~~~~~~~~~~ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-18-philmd@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Markus Armbruster --- util/vhost-user-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/vhost-user-server.c b/util/vhost-user-server.c index b4b6bf30a211..5ccc6d24a0c0 100644 --- a/util/vhost-user-server.c +++ b/util/vhost-user-server.c @@ -278,7 +278,7 @@ set_watch(VuDev *vu_dev, int fd, int vu_evt, VuFdWatch *vu_fd_watch = find_vu_fd_watch(server, fd); if (!vu_fd_watch) { - VuFdWatch *vu_fd_watch = g_new0(VuFdWatch, 1); + vu_fd_watch = g_new0(VuFdWatch, 1); QTAILQ_INSERT_TAIL(&server->vu_fd_watches, vu_fd_watch, next); From 7f087a323768585bb6063a1ee05a03a52b6a0b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:31 +0200 Subject: [PATCH 065/208] linux-user/strace: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: linux-user/strace.c: In function ‘print_sockaddr’: linux-user/strace.c:370:17: warning: declaration of ‘i’ shadows a previous local [-Wshadow=compatible-local] 370 | int i; | ^ linux-user/strace.c:361:9: note: shadowed declaration is here 361 | int i; | ^ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-20-philmd@linaro.org> Signed-off-by: Markus Armbruster --- linux-user/strace.c | 1 - 1 file changed, 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index e0ab8046ec15..cf26e5526436 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -367,7 +367,6 @@ print_sockaddr(abi_ulong addr, abi_long addrlen, int last) switch (sa_family) { case AF_UNIX: { struct target_sockaddr_un *un = (struct target_sockaddr_un *)sa; - int i; qemu_log("{sun_family=AF_UNIX,sun_path=\""); for (i = 0; i < addrlen - offsetof(struct target_sockaddr_un, sun_path) && From 720d6bcdbb9fd6781025f245c8d02ce179a2fc86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:32 +0200 Subject: [PATCH 066/208] sysemu/device_tree: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: hw/mips/boston.c:472:5: error: declaration shadows a local variable [-Werror,-Wshadow] qemu_fdt_setprop_cells(fdt, name, "reg", reg_base, reg_size); ^ include/sysemu/device_tree.h:129:13: note: expanded from macro 'qemu_fdt_setprop_cells' int i; ^ hw/mips/boston.c:461:9: note: previous declaration is here int i; ^ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-21-philmd@linaro.org> Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- include/sysemu/device_tree.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h index ca5339beae8e..8eab39593418 100644 --- a/include/sysemu/device_tree.h +++ b/include/sysemu/device_tree.h @@ -126,10 +126,8 @@ int qemu_fdt_add_path(void *fdt, const char *path); #define qemu_fdt_setprop_cells(fdt, node_path, property, ...) \ do { \ uint32_t qdt_tmp[] = { __VA_ARGS__ }; \ - int i; \ - \ - for (i = 0; i < ARRAY_SIZE(qdt_tmp); i++) { \ - qdt_tmp[i] = cpu_to_be32(qdt_tmp[i]); \ + for (unsigned i_ = 0; i_ < ARRAY_SIZE(qdt_tmp); i_++) { \ + qdt_tmp[i_] = cpu_to_be32(qdt_tmp[i_]); \ } \ qemu_fdt_setprop(fdt, node_path, property, qdt_tmp, \ sizeof(qdt_tmp)); \ From 083f450f659c0d34766d80a99878d2a1e5f8f495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:33 +0200 Subject: [PATCH 067/208] softmmu/memory: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: softmmu/memory.c: In function ‘mtree_print_mr’: softmmu/memory.c:3236:27: warning: declaration of ‘ml’ shadows a previous local [-Wshadow=compatible-local] 3236 | MemoryRegionList *ml; | ^~ softmmu/memory.c:3213:32: note: shadowed declaration is here 3213 | MemoryRegionList *new_ml, *ml, *next_ml; | ^~ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-22-philmd@linaro.org> Reviewed-by: Peter Xu Signed-off-by: Markus Armbruster --- softmmu/memory.c | 1 - 1 file changed, 1 deletion(-) diff --git a/softmmu/memory.c b/softmmu/memory.c index c0383a163d6a..234bd7b11611 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -3245,7 +3245,6 @@ static void mtree_print_mr(const MemoryRegion *mr, unsigned int level, } if (mr->alias) { - MemoryRegionList *ml; bool found = false; /* check if the alias is already in the queue */ From 6ba9b60a93d4f4df70205cbeb6c547a863f3c170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:12:34 +0200 Subject: [PATCH 068/208] softmmu/physmem: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: softmmu/physmem.c: In function ‘cpu_physical_memory_snapshot_and_clear_dirty’: softmmu/physmem.c:916:27: warning: declaration of ‘offset’ shadows a parameter [-Wshadow=compatible-local] 916 | unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE; | ^~~~~~ softmmu/physmem.c:892:31: note: shadowed declaration is here 892 | (MemoryRegion *mr, hwaddr offset, hwaddr length, unsigned client) | ~~~~~~~^~~~~~ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904161235.84651-23-philmd@linaro.org> Reviewed-by: Daniel P. Berrangé Reviewed-by: Peter Xu Signed-off-by: Markus Armbruster --- softmmu/physmem.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 4f6ca653b3a3..309653c72213 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -913,16 +913,16 @@ DirtyBitmapSnapshot *cpu_physical_memory_snapshot_and_clear_dirty while (page < end) { unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE; - unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE; + unsigned long ofs = page % DIRTY_MEMORY_BLOCK_SIZE; unsigned long num = MIN(end - page, - DIRTY_MEMORY_BLOCK_SIZE - offset); + DIRTY_MEMORY_BLOCK_SIZE - ofs); - assert(QEMU_IS_ALIGNED(offset, (1 << BITS_PER_LEVEL))); + assert(QEMU_IS_ALIGNED(ofs, (1 << BITS_PER_LEVEL))); assert(QEMU_IS_ALIGNED(num, (1 << BITS_PER_LEVEL))); - offset >>= BITS_PER_LEVEL; + ofs >>= BITS_PER_LEVEL; bitmap_copy_and_clear_atomic(snap->dirty + dest, - blocks->blocks[idx] + offset, + blocks->blocks[idx] + ofs, num); page += num; dest += num >> BITS_PER_LEVEL; From 5e0528a72570e95945eac841b0871f0cbba777b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:28:22 +0200 Subject: [PATCH 069/208] hw/core/machine: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: hw/core/machine.c: In function ‘machine_initfn’: hw/core/machine.c:1081:17: warning: declaration of ‘obj’ shadows a parameter [-Wshadow=compatible-local] 1081 | Object *obj = OBJECT(ms); | ^~~ hw/core/machine.c:1065:36: note: shadowed declaration is here 1065 | static void machine_initfn(Object *obj) | ~~~~~~~~^~~ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904162824.85385-2-philmd@linaro.org> Reviewed-by: Peter Maydell Signed-off-by: Markus Armbruster --- hw/core/machine.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index cb38b8cf4cb4..a232ae0bcdbd 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -1082,8 +1082,6 @@ static void machine_initfn(Object *obj) ms->maxram_size = mc->default_ram_size; if (mc->nvdimm_supported) { - Object *obj = OBJECT(ms); - ms->nvdimms_state = g_new0(NVDIMMState, 1); object_property_add_bool(obj, "nvdimm", machine_get_nvdimm, machine_set_nvdimm); From 1cc0c5dd38884a7c54bc806bb0ae182db275faf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 4 Sep 2023 18:28:23 +0200 Subject: [PATCH 070/208] hw/intc/openpic: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: hw/intc/openpic.c: In function ‘openpic_gbl_write’: hw/intc/openpic.c:614:17: warning: declaration of ‘idx’ shadows a previous local [-Wshadow=compatible-local] 614 | int idx; | ^~~ hw/intc/openpic.c:568:9: note: shadowed declaration is here 568 | int idx; | ^~~ Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20230904162824.85385-3-philmd@linaro.org> Reviewed-by: Peter Maydell Signed-off-by: Markus Armbruster --- hw/intc/openpic.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c index c757adbe5382..a6f91d4bcdf7 100644 --- a/hw/intc/openpic.c +++ b/hw/intc/openpic.c @@ -610,11 +610,8 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val, case 0x10B0: case 0x10C0: case 0x10D0: - { - int idx; - idx = (addr - 0x10A0) >> 4; - write_IRQreg_ivpr(opp, opp->irq_ipi0 + idx, val); - } + idx = (addr - 0x10A0) >> 4; + write_IRQreg_ivpr(opp, opp->irq_ipi0 + idx, val); break; case 0x10E0: /* SPVE */ opp->spve = val & opp->vector_mask; From 90231ce1a355ce07b71f9b82446a40ac866585de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 18 Sep 2023 16:58:43 +0200 Subject: [PATCH 071/208] hw/ppc: Clean up local variable shadowing in _FDT helper routine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this fixes numerous warnings of this type : In file included from ../hw/ppc/spapr_pci.c:43: ../hw/ppc/spapr_pci.c: In function ‘spapr_dt_phb’: ../include/hw/ppc/fdt.h:18:13: warning: declaration of ‘ret’ shadows a previous local [-Wshadow=compatible-local] 18 | int ret = (exp); \ | ^~~ ../hw/ppc/spapr_pci.c:2355:5: note: in expansion of macro ‘_FDT’ 2355 | _FDT(bus_off = fdt_add_subnode(fdt, 0, phb->dtbusname)); | ^~~~ ../hw/ppc/spapr_pci.c:2311:24: note: shadowed declaration is here 2311 | int bus_off, i, j, ret; | ^~~ Signed-off-by: Cédric Le Goater Message-ID: <20230918145850.241074-2-clg@kaod.org> Reviewed-by: Harsh Prateek Bora Signed-off-by: Markus Armbruster --- include/hw/ppc/fdt.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/hw/ppc/fdt.h b/include/hw/ppc/fdt.h index a8cd85069fe0..b56ac2a8cbb5 100644 --- a/include/hw/ppc/fdt.h +++ b/include/hw/ppc/fdt.h @@ -15,10 +15,10 @@ #define _FDT(exp) \ do { \ - int ret = (exp); \ - if (ret < 0) { \ - error_report("error creating device tree: %s: %s", \ - #exp, fdt_strerror(ret)); \ + int _ret = (exp); \ + if (_ret < 0) { \ + error_report("error creating device tree: %s: %s", \ + #exp, fdt_strerror(_ret)); \ exit(1); \ } \ } while (0) From 694616d68455eaa14f860e7a2bbe41043e8340d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 18 Sep 2023 16:58:44 +0200 Subject: [PATCH 072/208] pnv/psi: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to fix : ../hw/ppc/pnv_psi.c: In function ‘pnv_psi_p9_mmio_write’: ../hw/ppc/pnv_psi.c:741:24: warning: declaration of ‘addr’ shadows a parameter [-Wshadow=compatible-local] 741 | hwaddr addr = val & ~(PSIHB9_ESB_CI_VALID | PSIHB10_ESB_CI_64K); | ^~~~ ../hw/ppc/pnv_psi.c:702:56: note: shadowed declaration is here 702 | static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr, | ~~~~~~~^~~~ Signed-off-by: Cédric Le Goater Message-ID: <20230918145850.241074-3-clg@kaod.org> Reviewed-by: Harsh Prateek Bora Signed-off-by: Markus Armbruster --- hw/ppc/pnv_psi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c index daaa2f0575fd..26460d210deb 100644 --- a/hw/ppc/pnv_psi.c +++ b/hw/ppc/pnv_psi.c @@ -738,8 +738,9 @@ static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr, } } else { if (!(psi->regs[reg] & PSIHB9_ESB_CI_VALID)) { - hwaddr addr = val & ~(PSIHB9_ESB_CI_VALID | PSIHB10_ESB_CI_64K); - memory_region_add_subregion(sysmem, addr, + hwaddr esb_addr = + val & ~(PSIHB9_ESB_CI_VALID | PSIHB10_ESB_CI_64K); + memory_region_add_subregion(sysmem, esb_addr, &psi9->source.esb_mmio); } } From bd87a59f52c85e504323c3dbdacc84e2cefce8d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 18 Sep 2023 16:58:45 +0200 Subject: [PATCH 073/208] spapr: Clean up local variable shadowing in spapr_dt_cpus() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a helper routine defining one CPU device node to fix this warning : ../hw/ppc/spapr.c: In function ‘spapr_dt_cpus’: ../hw/ppc/spapr.c:812:19: warning: declaration of ‘cs’ shadows a previous local [-Wshadow=compatible-local] 812 | CPUState *cs = rev[i]; | ^~ ../hw/ppc/spapr.c:786:15: note: shadowed declaration is here 786 | CPUState *cs; | ^~ Signed-off-by: Cédric Le Goater Message-ID: <20230918145850.241074-4-clg@kaod.org> Reviewed-by: Harsh Prateek Bora Signed-off-by: Markus Armbruster --- hw/ppc/spapr.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 1f1aa2a6d481..612dbdf35614 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -780,6 +780,26 @@ static void spapr_dt_cpu(CPUState *cs, void *fdt, int offset, pcc->lrg_decr_bits))); } +static void spapr_dt_one_cpu(void *fdt, SpaprMachineState *spapr, CPUState *cs, + int cpus_offset) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + int index = spapr_get_vcpu_id(cpu); + DeviceClass *dc = DEVICE_GET_CLASS(cs); + g_autofree char *nodename = NULL; + int offset; + + if (!spapr_is_thread0_in_vcore(spapr, cpu)) { + return; + } + + nodename = g_strdup_printf("%s@%x", dc->fw_name, index); + offset = fdt_add_subnode(fdt, cpus_offset, nodename); + _FDT(offset); + spapr_dt_cpu(cs, fdt, offset, spapr); +} + + static void spapr_dt_cpus(void *fdt, SpaprMachineState *spapr) { CPUState **rev; @@ -809,21 +829,7 @@ static void spapr_dt_cpus(void *fdt, SpaprMachineState *spapr) } for (i = n_cpus - 1; i >= 0; i--) { - CPUState *cs = rev[i]; - PowerPCCPU *cpu = POWERPC_CPU(cs); - int index = spapr_get_vcpu_id(cpu); - DeviceClass *dc = DEVICE_GET_CLASS(cs); - g_autofree char *nodename = NULL; - int offset; - - if (!spapr_is_thread0_in_vcore(spapr, cpu)) { - continue; - } - - nodename = g_strdup_printf("%s@%x", dc->fw_name, index); - offset = fdt_add_subnode(fdt, cpus_offset, nodename); - _FDT(offset); - spapr_dt_cpu(cs, fdt, offset, spapr); + spapr_dt_one_cpu(fdt, spapr, rev[i], cpus_offset); } g_free(rev); From c0b648d9e9747f44fc3c4503b3a06741b0d6e4a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 18 Sep 2023 16:58:46 +0200 Subject: [PATCH 074/208] spapr: Clean up local variable shadowing in spapr_init_cpus() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove extra 'i' variable to fix this warning : ../hw/ppc/spapr.c: In function ‘spapr_init_cpus’: ../hw/ppc/spapr.c:2668:13: warning: declaration of ‘i’ shadows a previous local [-Wshadow=compatible-local] 2668 | int i; | ^ ../hw/ppc/spapr.c:2645:9: note: shadowed declaration is here 2645 | int i; | ^ Signed-off-by: Cédric Le Goater Message-ID: <20230918145850.241074-5-clg@kaod.org> Reviewed-by: Harsh Prateek Bora Signed-off-by: Markus Armbruster --- hw/ppc/spapr.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 612dbdf35614..4fe82e490a0a 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2665,8 +2665,6 @@ static void spapr_init_cpus(SpaprMachineState *spapr) } if (smc->pre_2_10_has_unused_icps) { - int i; - for (i = 0; i < spapr_max_server_number(spapr); i++) { /* Dummy entries get deregistered when real ICPState objects * are registered during CPU core hotplug. From 01a78f23cbaf15359a051b45c1df05269d5aa4d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 18 Sep 2023 16:58:47 +0200 Subject: [PATCH 075/208] spapr: Clean up local variable shadowing in spapr_get_fw_dev_path() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename PCIDevice variable to avoid this warning : ../hw/ppc/spapr.c: In function ‘spapr_get_fw_dev_path’: ../hw/ppc/spapr.c:3217:20: warning: declaration of ‘pcidev’ shadows a previous local [-Wshadow=compatible-local] 3217 | PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); | ^~~~~~ ../hw/ppc/spapr.c:3147:16: note: shadowed declaration is here 3147 | PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); | ^~~~~~ Signed-off-by: Cédric Le Goater Message-ID: <20230918145850.241074-6-clg@kaod.org> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Markus Armbruster --- hw/ppc/spapr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 4fe82e490a0a..d4230d3647a3 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3214,8 +3214,8 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, if (g_str_equal("pci-bridge", qdev_fw_name(dev))) { /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */ - PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); - return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn)); + PCIDevice *pdev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); + return g_strdup_printf("pci@%x", PCI_SLOT(pdev->devfn)); } if (pcidev) { From bea3d6e745fe34ca51780b623b10675ed1975b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 18 Sep 2023 16:58:48 +0200 Subject: [PATCH 076/208] spapr/drc: Clean up local variable shadowing in rtas_ibm_configure_connector() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove extra 'drc_index' variable to avoid this warning : ../hw/ppc/spapr_drc.c: In function ‘rtas_ibm_configure_connector’: ../hw/ppc/spapr_drc.c:1240:26: warning: declaration of ‘drc_index’ shadows a previous local [-Wshadow=compatible-local] 1240 | uint32_t drc_index = spapr_drc_index(drc); | ^~~~~~~~~ ../hw/ppc/spapr_drc.c:1155:14: note: shadowed declaration is here 1155 | uint32_t drc_index; | ^~~~~~~~~ Signed-off-by: Cédric Le Goater Message-ID: <20230918145850.241074-7-clg@kaod.org> Reviewed-by: Harsh Prateek Bora Signed-off-by: Markus Armbruster --- hw/ppc/spapr_drc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index b5c400a94d1c..843e318312d3 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -1237,8 +1237,6 @@ static void rtas_ibm_configure_connector(PowerPCCPU *cpu, case FDT_END_NODE: drc->ccs_depth--; if (drc->ccs_depth == 0) { - uint32_t drc_index = spapr_drc_index(drc); - /* done sending the device tree, move to configured state */ trace_spapr_drc_set_configured(drc_index); drc->state = drck->ready_state; From 15675f2318142f8fbfd17b161604fb4f5e9f420e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 18 Sep 2023 16:58:49 +0200 Subject: [PATCH 077/208] spapr/pci: Clean up local variable shadowing in spapr_phb_realize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename SysBusDevice variable to avoid this warning : ../hw/ppc/spapr_pci.c: In function ‘spapr_phb_realize’: ../hw/ppc/spapr_pci.c:1872:24: warning: declaration of ‘s’ shadows a previous local [-Wshadow=local] 1872 | SpaprPhbState *s; | ^ ../hw/ppc/spapr_pci.c:1829:19: note: shadowed declaration is here 1829 | SysBusDevice *s = SYS_BUS_DEVICE(dev); | ^ Signed-off-by: Cédric Le Goater Message-ID: <20230918145850.241074-8-clg@kaod.org> Reviewed-by: Harsh Prateek Bora Signed-off-by: Markus Armbruster --- hw/ppc/spapr_pci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index ce1495931744..370c5a90f218 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1826,9 +1826,9 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) (SpaprMachineState *) object_dynamic_cast(qdev_get_machine(), TYPE_SPAPR_MACHINE); SpaprMachineClass *smc = spapr ? SPAPR_MACHINE_GET_CLASS(spapr) : NULL; - SysBusDevice *s = SYS_BUS_DEVICE(dev); - SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(s); - PCIHostState *phb = PCI_HOST_BRIDGE(s); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(sbd); + PCIHostState *phb = PCI_HOST_BRIDGE(sbd); MachineState *ms = MACHINE(spapr); char *namebuf; int i; From 8cf52ff5c727519791eb897410f31c4ad27300cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 18 Sep 2023 16:58:50 +0200 Subject: [PATCH 078/208] spapr/drc: Clean up local variable shadowing in prop_get_fdt() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename 'name' variable to avoid this warning : ../hw/ppc/spapr_drc.c: In function ‘prop_get_fdt’: ../hw/ppc/spapr_drc.c:344:21: warning: declaration of ‘name’ shadows a parameter [-Wshadow=compatible-local] 344 | const char *name = NULL; | ^~~~ ../hw/ppc/spapr_drc.c:325:63: note: shadowed declaration is here 325 | static void prop_get_fdt(Object *obj, Visitor *v, const char *name, | ~~~~~~~~~~~~^~~~ Signed-off-by: Cédric Le Goater Message-ID: <20230918145850.241074-9-clg@kaod.org> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Harsh Prateek Bora Signed-off-by: Markus Armbruster --- hw/ppc/spapr_drc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 843e318312d3..2b99d3b4b1a6 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -341,7 +341,7 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, fdt_depth = 0; do { - const char *name = NULL; + const char *dt_name = NULL; const struct fdt_property *prop = NULL; int prop_len = 0, name_len = 0; uint32_t tag; @@ -351,8 +351,8 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, switch (tag) { case FDT_BEGIN_NODE: fdt_depth++; - name = fdt_get_name(fdt, fdt_offset, &name_len); - if (!visit_start_struct(v, name, NULL, 0, errp)) { + dt_name = fdt_get_name(fdt, fdt_offset, &name_len); + if (!visit_start_struct(v, dt_name, NULL, 0, errp)) { return; } break; @@ -369,8 +369,8 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, case FDT_PROP: { int i; prop = fdt_get_property_by_offset(fdt, fdt_offset, &prop_len); - name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); - if (!visit_start_list(v, name, NULL, 0, errp)) { + dt_name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); + if (!visit_start_list(v, dt_name, NULL, 0, errp)) { return; } for (i = 0; i < prop_len; i++) { From d8573092a49b3133530ceee35846a54e600f8a73 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Fri, 22 Sep 2023 12:57:42 +0200 Subject: [PATCH 079/208] test-throttle: don't shadow 'index' variable in do_test_accounting() Fixes build with -Wshadow=local Signed-off-by: Alberto Garcia Message-ID: <20230922105742.81317-1-berto@igalia.com> Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- tests/unit/test-throttle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test-throttle.c b/tests/unit/test-throttle.c index cb587e33e736..ac35d65d19b4 100644 --- a/tests/unit/test-throttle.c +++ b/tests/unit/test-throttle.c @@ -625,7 +625,7 @@ static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */ throttle_config_init(&cfg); for (i = 0; i < 3; i++) { - BucketType index = to_test[is_ops][i]; + index = to_test[is_ops][i]; cfg.buckets[index].avg = avg; } From 7b393b71424ba105f2b1c5f2c49f8d8710ad00eb Mon Sep 17 00:00:00 2001 From: Ani Sinha Date: Fri, 22 Sep 2023 18:12:02 +0530 Subject: [PATCH 080/208] hw/acpi: changes towards enabling -Wshadow=local Code changes in acpi that addresses all compiler complaints coming from enabling -Wshadow flags. Enabling -Wshadow catches cases of local variables shadowing other local variables or parameters. These makes the code confusing and/or adds bugs that are difficult to catch. See also Subject: Help wanted for enabling -Wshadow=local Message-Id: <87r0mqlf9x.fsf@pond.sub.org> https://lore.kernel.org/qemu-devel/87r0mqlf9x.fsf@pond.sub.org The code is tested to build with and without the flag turned on. CC: Markus Armbruster CC: Philippe Mathieu-Daude CC: mst@redhat.com CC: imammedo@redhat.com Signed-off-by: Ani Sinha Message-ID: <20230922124203.127110-1-anisinha@redhat.com> Reviewed-by: Michael S. Tsirkin [Commit message tweaked] Signed-off-by: Markus Armbruster --- hw/acpi/cpu_hotplug.c | 25 +++++++++++++------------ hw/i386/acpi-build.c | 24 ++++++++++++------------ hw/smbios/smbios.c | 37 +++++++++++++++++++------------------ 3 files changed, 44 insertions(+), 42 deletions(-) diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c index ff14c3f4106f..634bbecb319c 100644 --- a/hw/acpi/cpu_hotplug.c +++ b/hw/acpi/cpu_hotplug.c @@ -265,26 +265,27 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine, /* build Processor object for each processor */ for (i = 0; i < apic_ids->len; i++) { - int apic_id = apic_ids->cpus[i].arch_id; + int cpu_apic_id = apic_ids->cpus[i].arch_id; - assert(apic_id < ACPI_CPU_HOTPLUG_ID_LIMIT); + assert(cpu_apic_id < ACPI_CPU_HOTPLUG_ID_LIMIT); - dev = aml_processor(i, 0, 0, "CP%.02X", apic_id); + dev = aml_processor(i, 0, 0, "CP%.02X", cpu_apic_id); method = aml_method("_MAT", 0, AML_NOTSERIALIZED); aml_append(method, - aml_return(aml_call2(CPU_MAT_METHOD, aml_int(apic_id), aml_int(i)) + aml_return(aml_call2(CPU_MAT_METHOD, + aml_int(cpu_apic_id), aml_int(i)) )); aml_append(dev, method); method = aml_method("_STA", 0, AML_NOTSERIALIZED); aml_append(method, - aml_return(aml_call1(CPU_STATUS_METHOD, aml_int(apic_id)))); + aml_return(aml_call1(CPU_STATUS_METHOD, aml_int(cpu_apic_id)))); aml_append(dev, method); method = aml_method("_EJ0", 1, AML_NOTSERIALIZED); aml_append(method, - aml_return(aml_call2(CPU_EJECT_METHOD, aml_int(apic_id), + aml_return(aml_call2(CPU_EJECT_METHOD, aml_int(cpu_apic_id), aml_arg(0))) ); aml_append(dev, method); @@ -298,11 +299,11 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine, /* Arg0 = APIC ID */ method = aml_method(AML_NOTIFY_METHOD, 2, AML_NOTSERIALIZED); for (i = 0; i < apic_ids->len; i++) { - int apic_id = apic_ids->cpus[i].arch_id; + int cpu_apic_id = apic_ids->cpus[i].arch_id; - if_ctx = aml_if(aml_equal(aml_arg(0), aml_int(apic_id))); + if_ctx = aml_if(aml_equal(aml_arg(0), aml_int(cpu_apic_id))); aml_append(if_ctx, - aml_notify(aml_name("CP%.02X", apic_id), aml_arg(1)) + aml_notify(aml_name("CP%.02X", cpu_apic_id), aml_arg(1)) ); aml_append(method, if_ctx); } @@ -319,13 +320,13 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine, aml_varpackage(x86ms->apic_id_limit); for (i = 0, apic_idx = 0; i < apic_ids->len; i++) { - int apic_id = apic_ids->cpus[i].arch_id; + int cpu_apic_id = apic_ids->cpus[i].arch_id; - for (; apic_idx < apic_id; apic_idx++) { + for (; apic_idx < cpu_apic_id; apic_idx++) { aml_append(pkg, aml_int(0)); } aml_append(pkg, aml_int(apic_ids->cpus[i].cpu ? 1 : 0)); - apic_idx = apic_id + 1; + apic_idx = cpu_apic_id + 1; } aml_append(sb_scope, aml_name_decl(CPU_ON_BITMAP, pkg)); aml_append(ctx, sb_scope); diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 4d2d40bab52f..95199c89008a 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1585,12 +1585,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_UID", aml_int(bus_num))); aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num))); if (pci_bus_is_cxl(bus)) { - struct Aml *pkg = aml_package(2); + struct Aml *aml_pkg = aml_package(2); aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0016"))); - aml_append(pkg, aml_eisaid("PNP0A08")); - aml_append(pkg, aml_eisaid("PNP0A03")); - aml_append(dev, aml_name_decl("_CID", pkg)); + aml_append(aml_pkg, aml_eisaid("PNP0A08")); + aml_append(aml_pkg, aml_eisaid("PNP0A03")); + aml_append(dev, aml_name_decl("_CID", aml_pkg)); build_cxl_osc_method(dev); } else if (pci_bus_is_express(bus)) { aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); @@ -1783,14 +1783,14 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, Object *pci_host = acpi_get_i386_pci_host(); if (pci_host) { - PCIBus *bus = PCI_HOST_BRIDGE(pci_host)->bus; - Aml *scope = aml_scope("PCI0"); + PCIBus *pbus = PCI_HOST_BRIDGE(pci_host)->bus; + Aml *ascope = aml_scope("PCI0"); /* Scan all PCI buses. Generate tables to support hotplug. */ - build_append_pci_bus_devices(scope, bus); - if (object_property_find(OBJECT(bus), ACPI_PCIHP_PROP_BSEL)) { - build_append_pcihp_slots(scope, bus); + build_append_pci_bus_devices(ascope, pbus); + if (object_property_find(OBJECT(pbus), ACPI_PCIHP_PROP_BSEL)) { + build_append_pcihp_slots(ascope, pbus); } - aml_append(sb_scope, scope); + aml_append(sb_scope, ascope); } } @@ -1842,10 +1842,10 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, bool has_pcnt; Object *pci_host = acpi_get_i386_pci_host(); - PCIBus *bus = PCI_HOST_BRIDGE(pci_host)->bus; + PCIBus *b = PCI_HOST_BRIDGE(pci_host)->bus; scope = aml_scope("\\_SB.PCI0"); - has_pcnt = build_append_notfication_callback(scope, bus); + has_pcnt = build_append_notfication_callback(scope, b); if (has_pcnt) { aml_append(dsdt, scope); } diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c index b753705856aa..2a90601ac5d9 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c @@ -1423,13 +1423,14 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) if (!qemu_opts_validate(opts, qemu_smbios_type8_opts, errp)) { return; } - struct type8_instance *t; - t = g_new0(struct type8_instance, 1); - save_opt(&t->internal_reference, opts, "internal_reference"); - save_opt(&t->external_reference, opts, "external_reference"); - t->connector_type = qemu_opt_get_number(opts, "connector_type", 0); - t->port_type = qemu_opt_get_number(opts, "port_type", 0); - QTAILQ_INSERT_TAIL(&type8, t, next); + struct type8_instance *t8_i; + t8_i = g_new0(struct type8_instance, 1); + save_opt(&t8_i->internal_reference, opts, "internal_reference"); + save_opt(&t8_i->external_reference, opts, "external_reference"); + t8_i->connector_type = qemu_opt_get_number(opts, + "connector_type", 0); + t8_i->port_type = qemu_opt_get_number(opts, "port_type", 0); + QTAILQ_INSERT_TAIL(&type8, t8_i, next); return; case 11: if (!qemu_opts_validate(opts, qemu_smbios_type11_opts, errp)) { @@ -1452,27 +1453,27 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) type17.speed = qemu_opt_get_number(opts, "speed", 0); return; case 41: { - struct type41_instance *t; + struct type41_instance *t41_i; Error *local_err = NULL; if (!qemu_opts_validate(opts, qemu_smbios_type41_opts, errp)) { return; } - t = g_new0(struct type41_instance, 1); - save_opt(&t->designation, opts, "designation"); - t->kind = qapi_enum_parse(&type41_kind_lookup, - qemu_opt_get(opts, "kind"), - 0, &local_err) + 1; - t->kind |= 0x80; /* enabled */ + t41_i = g_new0(struct type41_instance, 1); + save_opt(&t41_i->designation, opts, "designation"); + t41_i->kind = qapi_enum_parse(&type41_kind_lookup, + qemu_opt_get(opts, "kind"), + 0, &local_err) + 1; + t41_i->kind |= 0x80; /* enabled */ if (local_err != NULL) { error_propagate(errp, local_err); - g_free(t); + g_free(t41_i); return; } - t->instance = qemu_opt_get_number(opts, "instance", 1); - save_opt(&t->pcidev, opts, "pcidev"); + t41_i->instance = qemu_opt_get_number(opts, "instance", 1); + save_opt(&t41_i->pcidev, opts, "pcidev"); - QTAILQ_INSERT_TAIL(&type41, t, next); + QTAILQ_INSERT_TAIL(&type41, t41_i, next); return; } default: From 33b3b4aded2eb56d505d563e4788e0654a7e9f2b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 22 Sep 2023 16:29:41 +0100 Subject: [PATCH 081/208] hw/intc/arm_gicv3_its: Avoid shadowing variable in do_process_its_cmd() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid shadowing a local variable in do_process_its_cmd(): ../../hw/intc/arm_gicv3_its.c:548:17: warning: declaration of ‘ite’ shadows a previous local [-Wshadow=compatible-local] 548 | ITEntry ite = {}; | ^~~ ../../hw/intc/arm_gicv3_its.c:518:13: note: shadowed declaration is here 518 | ITEntry ite; | ^~~ Signed-off-by: Peter Maydell Message-ID: <20230922152944.3583438-2-peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Eric Auger Signed-off-by: Markus Armbruster --- hw/intc/arm_gicv3_its.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 5f552b4d37f4..52e9aca9c65f 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -545,10 +545,10 @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid, } if (cmdres == CMD_CONTINUE_OK && cmd == DISCARD) { - ITEntry ite = {}; + ITEntry i = {}; /* remove mapping from interrupt translation table */ - ite.valid = false; - return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL; + i.valid = false; + return update_ite(s, eventid, &dte, &i) ? CMD_CONTINUE_OK : CMD_STALL; } return CMD_CONTINUE_OK; } From b2e7e2048bbe7a82b921d9ca71da9aec1668fcfe Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 22 Sep 2023 16:29:42 +0100 Subject: [PATCH 082/208] hw/misc/arm_sysctl.c: Avoid shadowing local variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid shadowing a local variable in arm_sysctl_write(): ../../hw/misc/arm_sysctl.c: In function ‘arm_sysctl_write’: ../../hw/misc/arm_sysctl.c:537:26: warning: declaration of ‘val’ shadows a parameter [-Wshadow=local] 537 | uint32_t val; | ^~~ ../../hw/misc/arm_sysctl.c:388:39: note: shadowed declaration is here 388 | uint64_t val, unsigned size) | ~~~~~~~~~^~~ Signed-off-by: Peter Maydell Message-ID: <20230922152944.3583438-3-peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Eric Auger Signed-off-by: Markus Armbruster --- hw/misc/arm_sysctl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c index 42d46938543b..3e4f4b052443 100644 --- a/hw/misc/arm_sysctl.c +++ b/hw/misc/arm_sysctl.c @@ -534,12 +534,12 @@ static void arm_sysctl_write(void *opaque, hwaddr offset, s->sys_cfgstat |= 2; /* error */ } } else { - uint32_t val; + uint32_t data; if (!vexpress_cfgctrl_read(s, dcc, function, site, position, - device, &val)) { + device, &data)) { s->sys_cfgstat |= 2; /* error */ } else { - s->sys_cfgdata = val; + s->sys_cfgdata = data; } } } From 9e2135ee93ad84119642787e3fb8264b6d1c7ef5 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 22 Sep 2023 16:29:43 +0100 Subject: [PATCH 083/208] hw/arm/smmuv3.c: Avoid shadowing variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid shadowing a variable in smmuv3_notify_iova(): ../../hw/arm/smmuv3.c: In function ‘smmuv3_notify_iova’: ../../hw/arm/smmuv3.c:1043:23: warning: declaration of ‘event’ shadows a previous local [-Wshadow=local] 1043 | SMMUEventInfo event = {.inval_ste_allowed = true}; | ^~~~~ ../../hw/arm/smmuv3.c:1038:19: note: shadowed declaration is here 1038 | IOMMUTLBEvent event; | ^~~~~ Signed-off-by: Peter Maydell Message-ID: <20230922152944.3583438-4-peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Eric Auger Signed-off-by: Markus Armbruster --- hw/arm/smmuv3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 1e9be8e89afc..6f2b2bd45f96 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -1040,8 +1040,8 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, SMMUv3State *s = sdev->smmu; if (!tg) { - SMMUEventInfo event = {.inval_ste_allowed = true}; - SMMUTransCfg *cfg = smmuv3_get_config(sdev, &event); + SMMUEventInfo eventinfo = {.inval_ste_allowed = true}; + SMMUTransCfg *cfg = smmuv3_get_config(sdev, &eventinfo); SMMUTransTableInfo *tt; if (!cfg) { From 84abccdd39d6c011971a2a41e7b64f7084e28da8 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 22 Sep 2023 16:29:44 +0100 Subject: [PATCH 084/208] hw/arm/smmuv3-internal.h: Don't use locals in statement macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The STE_CTXPTR() and STE_S2TTB() macros both extract two halves of an address from fields in the STE and combine them into a single value to return. The current code for this uses a GCC statement expression. There are two problems with this: (1) The type chosen for the variable in the statement expr is 'unsigned long', which might not be 64 bits (2) the name chosen for the variable causes -Wshadow warnings because it's the same as a variable in use at the callsite: In file included from ../../hw/arm/smmuv3.c:34: ../../hw/arm/smmuv3.c: In function ‘smmu_get_cd’: ../../hw/arm/smmuv3-internal.h:538:23: warning: declaration of ‘addr’ shadows a previous local [-Wshadow=compatible-local] 538 | unsigned long addr; \ | ^~~~ ../../hw/arm/smmuv3.c:339:23: note: in expansion of macro ‘STE_CTXPTR’ 339 | dma_addr_t addr = STE_CTXPTR(ste); | ^~~~~~~~~~ ../../hw/arm/smmuv3.c:339:16: note: shadowed declaration is here 339 | dma_addr_t addr = STE_CTXPTR(ste); | ^~~~ Sidestep both of these problems by just using a single expression rather than a statement expr. For CMD_ADDR, we got the type of the variable right but still run into -Wshadow problems: In file included from ../../hw/arm/smmuv3.c:34: ../../hw/arm/smmuv3.c: In function ‘smmuv3_range_inval’: ../../hw/arm/smmuv3-internal.h:334:22: warning: declaration of ‘addr’ shadows a previous local [-Wshadow=compatible-local] 334 | uint64_t addr = high << 32 | (low << 12); \ | ^~~~ ../../hw/arm/smmuv3.c:1104:28: note: in expansion of macro ‘CMD_ADDR’ 1104 | dma_addr_t end, addr = CMD_ADDR(cmd); | ^~~~~~~~ ../../hw/arm/smmuv3.c:1104:21: note: shadowed declaration is here 1104 | dma_addr_t end, addr = CMD_ADDR(cmd); | ^~~~ so convert it too. CD_TTB has neither problem, but it is the only other macro in the file that uses this pattern, so we convert it also for consistency's sake. We use extract64() rather than extract32() to avoid having to explicitly cast the result to uint64_t. Signed-off-by: Peter Maydell Message-ID: <20230922152944.3583438-5-peter.maydell@linaro.org> Reviewed-by: Eric Auger Signed-off-by: Markus Armbruster --- hw/arm/smmuv3-internal.h | 43 +++++++++++++--------------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 6d1c1edab7be..648c2e37a279 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -328,12 +328,9 @@ enum { /* Command completion notification */ #define CMD_TTL(x) extract32((x)->word[2], 8 , 2) #define CMD_TG(x) extract32((x)->word[2], 10, 2) #define CMD_STE_RANGE(x) extract32((x)->word[2], 0 , 5) -#define CMD_ADDR(x) ({ \ - uint64_t high = (uint64_t)(x)->word[3]; \ - uint64_t low = extract32((x)->word[2], 12, 20); \ - uint64_t addr = high << 32 | (low << 12); \ - addr; \ - }) +#define CMD_ADDR(x) \ + (((uint64_t)((x)->word[3]) << 32) | \ + ((extract64((x)->word[2], 12, 20)) << 12)) #define SMMU_FEATURE_2LVL_STE (1 << 0) @@ -533,21 +530,13 @@ typedef struct CD { #define STE_S2S(x) extract32((x)->word[5], 25, 1) #define STE_S2R(x) extract32((x)->word[5], 26, 1) -#define STE_CTXPTR(x) \ - ({ \ - unsigned long addr; \ - addr = (uint64_t)extract32((x)->word[1], 0, 16) << 32; \ - addr |= (uint64_t)((x)->word[0] & 0xffffffc0); \ - addr; \ - }) - -#define STE_S2TTB(x) \ - ({ \ - unsigned long addr; \ - addr = (uint64_t)extract32((x)->word[7], 0, 16) << 32; \ - addr |= (uint64_t)((x)->word[6] & 0xfffffff0); \ - addr; \ - }) +#define STE_CTXPTR(x) \ + ((extract64((x)->word[1], 0, 16) << 32) | \ + ((x)->word[0] & 0xffffffc0)) + +#define STE_S2TTB(x) \ + ((extract64((x)->word[7], 0, 16) << 32) | \ + ((x)->word[6] & 0xfffffff0)) static inline int oas2bits(int oas_field) { @@ -585,14 +574,10 @@ static inline int pa_range(STE *ste) #define CD_VALID(x) extract32((x)->word[0], 31, 1) #define CD_ASID(x) extract32((x)->word[1], 16, 16) -#define CD_TTB(x, sel) \ - ({ \ - uint64_t hi, lo; \ - hi = extract32((x)->word[(sel) * 2 + 3], 0, 19); \ - hi <<= 32; \ - lo = (x)->word[(sel) * 2 + 2] & ~0xfULL; \ - hi | lo; \ - }) +#define CD_TTB(x, sel) \ + ((extract64((x)->word[(sel) * 2 + 3], 0, 19) << 32) | \ + ((x)->word[(sel) * 2 + 2] & ~0xfULL)) + #define CD_HAD(x, sel) extract32((x)->word[(sel) * 2 + 2], 1, 1) #define CD_TSZ(x, sel) extract32((x)->word[0], (16 * (sel)) + 0, 6) From ce6c368d96ed88c2c8505c825b771e8632e84a88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Fri, 22 Sep 2023 17:59:21 +0200 Subject: [PATCH 085/208] aspeed/i2c: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove superfluous local 'data' variable and use the one define at the top of the routine. This fixes : ../hw/i2c/aspeed_i2c.c: In function ‘aspeed_i2c_bus_recv’: ../hw/i2c/aspeed_i2c.c:315:17: warning: declaration of ‘data’ shadows a previous local [-Wshadow=compatible-local] 315 | uint8_t data; | ^~~~ ../hw/i2c/aspeed_i2c.c:288:13: note: shadowed declaration is here 288 | uint8_t data; | ^~~~ Signed-off-by: Cédric Le Goater Message-ID: <20230922155924.1172019-2-clg@kaod.org> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Joel Stanley Signed-off-by: Markus Armbruster --- hw/i2c/aspeed_i2c.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index 7275d40749a9..1037c22b2f79 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -312,7 +312,6 @@ static void aspeed_i2c_bus_recv(AspeedI2CBus *bus) SHARED_ARRAY_FIELD_DP32(bus->regs, reg_pool_ctrl, RX_COUNT, i & 0xff); SHARED_ARRAY_FIELD_DP32(bus->regs, reg_cmd, RX_BUFF_EN, 0); } else if (SHARED_ARRAY_FIELD_EX32(bus->regs, reg_cmd, RX_DMA_EN)) { - uint8_t data; /* In new mode, clear how many bytes we RXed */ if (aspeed_i2c_is_new_mode(bus->controller)) { ARRAY_FIELD_DP32(bus->regs, I2CM_DMA_LEN_STS, RX_LEN, 0); From e8874c06a7da70a59c7c7ac2cf0c3612cbc82f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Fri, 22 Sep 2023 17:59:22 +0200 Subject: [PATCH 086/208] aspeed: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove superfluous local 'irq' variables and use the one define at the top of the routine. This fixes warnings in aspeed_soc_ast2600_realize() such as : ../hw/arm/aspeed_ast2600.c: In function ‘aspeed_soc_ast2600_realize’: ../hw/arm/aspeed_ast2600.c:420:18: warning: declaration of ‘irq’ shadows a previous local [-Wshadow=compatible-local] 420 | qemu_irq irq = aspeed_soc_get_irq(s, ASPEED_DEV_TIMER1 + i); | ^~~ ../hw/arm/aspeed_ast2600.c:312:14: note: shadowed declaration is here 312 | qemu_irq irq; | ^~~ Signed-off-by: Cédric Le Goater Message-ID: <20230922155924.1172019-3-clg@kaod.org> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Markus Armbruster --- hw/arm/aspeed_ast2600.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index a8b3a8065a11..e122e1c32d42 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -388,7 +388,7 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->timerctrl), 0, sc->memmap[ASPEED_DEV_TIMER1]); for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) { - qemu_irq irq = aspeed_soc_get_irq(s, ASPEED_DEV_TIMER1 + i); + irq = aspeed_soc_get_irq(s, ASPEED_DEV_TIMER1 + i); sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq); } @@ -413,8 +413,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) } aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_DEV_I2C]); for (i = 0; i < ASPEED_I2C_GET_CLASS(&s->i2c)->num_busses; i++) { - qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), - sc->irqmap[ASPEED_DEV_I2C] + i); + irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), + sc->irqmap[ASPEED_DEV_I2C] + i); /* The AST2600 I2C controller has one IRQ per bus. */ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c.busses[i]), 0, irq); } @@ -611,8 +611,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) } aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->i3c), 0, sc->memmap[ASPEED_DEV_I3C]); for (i = 0; i < ASPEED_I3C_NR_DEVICES; i++) { - qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), - sc->irqmap[ASPEED_DEV_I3C] + i); + irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), + sc->irqmap[ASPEED_DEV_I3C] + i); /* The AST2600 I3C controller has one IRQ per bus. */ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i3c.devices[i]), 0, irq); } From e407513d285b96594a2710c9b37dff7ce9632f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Fri, 22 Sep 2023 17:59:23 +0200 Subject: [PATCH 087/208] aspeed/i3c: Rename variable shadowing a local MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to fix warning : ../hw/i3c/aspeed_i3c.c: In function ‘aspeed_i3c_realize’: ../hw/i3c/aspeed_i3c.c:1959:17: warning: declaration of ‘dev’ shadows a parameter [-Wshadow=local] 1959 | Object *dev = OBJECT(&s->devices[i]); | ^~~ ../hw/i3c/aspeed_i3c.c:1942:45: note: shadowed declaration is here 1942 | static void aspeed_i3c_realize(DeviceState *dev, Error **errp) | ~~~~~~~~~~~~~^~~ Signed-off-by: Cédric Le Goater Message-ID: <20230922155924.1172019-4-clg@kaod.org> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Andrew Jeffery Signed-off-by: Markus Armbruster --- hw/misc/aspeed_i3c.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/misc/aspeed_i3c.c b/hw/misc/aspeed_i3c.c index f54f5da522b3..d1ff61767167 100644 --- a/hw/misc/aspeed_i3c.c +++ b/hw/misc/aspeed_i3c.c @@ -296,13 +296,13 @@ static void aspeed_i3c_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem); for (i = 0; i < ASPEED_I3C_NR_DEVICES; ++i) { - Object *dev = OBJECT(&s->devices[i]); + Object *i3c_dev = OBJECT(&s->devices[i]); - if (!object_property_set_uint(dev, "device-id", i, errp)) { + if (!object_property_set_uint(i3c_dev, "device-id", i, errp)) { return; } - if (!sysbus_realize(SYS_BUS_DEVICE(dev), errp)) { + if (!sysbus_realize(SYS_BUS_DEVICE(i3c_dev), errp)) { return; } From 62fcc4e872cf01350e4dd395c60c5c726121417f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Fri, 22 Sep 2023 17:59:24 +0200 Subject: [PATCH 088/208] aspeed/timer: Clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 8137355e850f ("aspeed/timer: Fix behaviour running Linux") introduced a MAX() expression to calculate the next timer deadline : return calculate_time(t, MAX(MAX(t->match[0], t->match[1]), 0)); The second MAX() is not necessary since the compared values are an unsigned and 0. Simply remove it and fix warning : ../hw/timer/aspeed_timer.c: In function ‘calculate_next’: ../include/qemu/osdep.h:396:31: warning: declaration of ‘_a’ shadows a previous local [-Wshadow=compatible-local] 396 | typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ | ^~ ../hw/timer/aspeed_timer.c:170:12: note: in expansion of macro ‘MAX’ 170 | next = MAX(MAX(calculate_match(t, 0), calculate_match(t, 1)), 0); | ^~~ ../hw/timer/aspeed_timer.c:170:16: note: in expansion of macro ‘MAX’ 170 | next = MAX(MAX(calculate_match(t, 0), calculate_match(t, 1)), 0); | ^~~ /home/legoater/work/qemu/qemu-aspeed.git/include/qemu/osdep.h:396:31: note: shadowed declaration is here 396 | typeof(1 ? (a) : (b)) _a = (a), _b = (b); \ | ^~ ../hw/timer/aspeed_timer.c:170:12: note: in expansion of macro ‘MAX’ 170 | next = MAX(MAX(calculate_match(t, 0), calculate_match(t, 1)), 0); | ^~~ Cc: Joel Stanley Cc: Andrew Jeffery Signed-off-by: Cédric Le Goater Message-ID: <20230922155924.1172019-5-clg@kaod.org> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Markus Armbruster --- hw/timer/aspeed_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c index 9c20b3d6ad8a..72161f07bbee 100644 --- a/hw/timer/aspeed_timer.c +++ b/hw/timer/aspeed_timer.c @@ -167,7 +167,7 @@ static uint64_t calculate_next(struct AspeedTimer *t) qemu_set_irq(t->irq, t->level); } - next = MAX(MAX(calculate_match(t, 0), calculate_match(t, 1)), 0); + next = MAX(calculate_match(t, 0), calculate_match(t, 1)); t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); return calculate_time(t, next); From a082739eb390d2aad679b5efa9afc40cfa2a496d Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Fri, 22 Sep 2023 12:04:10 -0400 Subject: [PATCH 089/208] intel_iommu: Fix shadow local variables on "size" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the warning of shadowed local variable: ../hw/i386/intel_iommu.c: In function ‘vtd_address_space_unmap’: ../hw/i386/intel_iommu.c:3773:18: warning: declaration of ‘size’ shadows a previous local [-Wshadow=compatible-local] 3773 | uint64_t size = mask + 1; | ^~~~ ../hw/i386/intel_iommu.c:3747:12: note: shadowed declaration is here 3747 | hwaddr size, remain; | ^~~~ Cc: Jason Wang Cc: Eric Auger Cc: Michael S. Tsirkin Cc: Markus Armbruster Signed-off-by: Peter Xu Message-ID: <20230922160410.138786-1-peterx@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Michael S. Tsirkin Signed-off-by: Markus Armbruster --- hw/i386/intel_iommu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index c0ce8966688d..2c832ab68b37 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -3744,7 +3744,7 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, /* Unmap the whole range in the notifier's scope. */ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n) { - hwaddr size, remain; + hwaddr total, remain; hwaddr start = n->start; hwaddr end = n->end; IntelIOMMUState *s = as->iommu_state; @@ -3765,7 +3765,7 @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n) } assert(start <= end); - size = remain = end - start + 1; + total = remain = end - start + 1; while (remain >= VTD_PAGE_SIZE) { IOMMUTLBEvent event; @@ -3793,10 +3793,10 @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n) trace_vtd_as_unmap_whole(pci_bus_num(as->bus), VTD_PCI_SLOT(as->devfn), VTD_PCI_FUNC(as->devfn), - n->start, size); + n->start, total); map.iova = n->start; - map.size = size - 1; /* Inclusive */ + map.size = total - 1; /* Inclusive */ iova_tree_remove(as->iova_tree, map); } From 3cc9fe177f412494f084923149338c51dd232b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Fri, 22 Sep 2023 17:06:43 +0100 Subject: [PATCH 090/208] crypto: remove shadowed 'ret' variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both instances of 'ret' are used to store a gnutls API return code. Signed-off-by: Daniel P. Berrangé Message-ID: <20230922160644.438631-2-berrange@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Markus Armbruster --- crypto/tls-cipher-suites.c | 1 - 1 file changed, 1 deletion(-) diff --git a/crypto/tls-cipher-suites.c b/crypto/tls-cipher-suites.c index 5e4f59746450..d0df4badc0fe 100644 --- a/crypto/tls-cipher-suites.c +++ b/crypto/tls-cipher-suites.c @@ -52,7 +52,6 @@ GByteArray *qcrypto_tls_cipher_suites_get_data(QCryptoTLSCipherSuites *obj, byte_array = g_byte_array_new(); for (i = 0;; i++) { - int ret; unsigned idx; const char *name; IANA_TLS_CIPHER cipher; From 0d57919acf27ca343981f69cec33463887e0a716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Fri, 22 Sep 2023 17:06:44 +0100 Subject: [PATCH 091/208] seccomp: avoid shadowing of 'action' variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is confusing as one 'action' variable is used for storing a SCMP_ enum value, while the other 'action' variable is used for storing a SECCOMP_ enum value. Signed-off-by: Daniel P. Berrangé Message-ID: <20230922160644.438631-3-berrange@redhat.com> Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- softmmu/qemu-seccomp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/softmmu/qemu-seccomp.c b/softmmu/qemu-seccomp.c index d66a2a12262c..4d7439e7f71e 100644 --- a/softmmu/qemu-seccomp.c +++ b/softmmu/qemu-seccomp.c @@ -283,9 +283,9 @@ static uint32_t qemu_seccomp_update_action(uint32_t action) if (action == SCMP_ACT_TRAP) { static int kill_process = -1; if (kill_process == -1) { - uint32_t action = SECCOMP_RET_KILL_PROCESS; + uint32_t testaction = SECCOMP_RET_KILL_PROCESS; - if (qemu_seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &action) == 0) { + if (qemu_seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &testaction) == 0) { kill_process = 1; } else { kill_process = 0; From e161785c05c8a96962a0ea87a3abefe158d8b035 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 22 Sep 2023 15:50:20 -0500 Subject: [PATCH 092/208] qemu-nbd: changes towards enabling -Wshadow=local MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address all compiler complaints from -Wshadow in qemu-nbd. Several instances of 'int ret' became shadows when commit 4fbec260 added 'ret' at a higher scope in main. More interesting was the 'void *ret' capturing the result of a pthread; where we were conceptually doing '(void*)(intptr_t)EXIT_FAILURE != NULL' which just feels wrong (even though it happens to compile correctly), so it was worth a better cleanup. Signed-off-by: Eric Blake Message-ID: <20230922205019.2755352-2-eblake@redhat.com> Reviewed-by: Daniel P. Berrangé Signed-off-by: Markus Armbruster --- qemu-nbd.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/qemu-nbd.c b/qemu-nbd.c index 70aa3c487a04..54faa87a0c0e 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -939,7 +939,6 @@ int main(int argc, char **argv) g_autoptr(GError) err = NULL; int stderr_fd[2]; pid_t pid; - int ret; if (!g_unix_open_pipe(stderr_fd, FD_CLOEXEC, &err)) { error_report("Error setting up communication pipe: %s", @@ -1172,7 +1171,6 @@ int main(int argc, char **argv) if (opts.device) { #if HAVE_NBD_DEVICE - int ret; ret = pthread_create(&client_thread, NULL, nbd_client_thread, &opts); if (ret != 0) { error_report("Failed to create client thread: %s", strerror(ret)); @@ -1219,9 +1217,10 @@ int main(int argc, char **argv) qemu_opts_del(sn_opts); if (opts.device) { - void *ret; - pthread_join(client_thread, &ret); - exit(ret != NULL); + void *result; + pthread_join(client_thread, &result); + ret = (intptr_t)result; + exit(ret); } else { exit(EXIT_SUCCESS); } From 010f5557ab1d5d14c3ffc023387289c68b889cc9 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 25 Sep 2023 14:30:20 +1000 Subject: [PATCH 093/208] hw/riscv: opentitan: Fixup local variables shadowing Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Bugs love to hide in such code. Evidence: "[PATCH v3 1/7] migration/rdma: Fix save_page method to fail on polling error". This patch removes the local variable shadowing. Tested by adding: --extra-cflags='-Wshadow=local -Wno-error=shadow=local -Wno-error=shadow=compatible-local' To configure Signed-off-by: Alistair Francis Message-ID: <20230925043023.71448-2-alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza Signed-off-by: Markus Armbruster --- hw/riscv/opentitan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index 6a2fcc4ade3c..436503f1ba64 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -227,7 +227,7 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) IRQ_M_TIMER)); /* SPI-Hosts */ - for (int i = 0; i < OPENTITAN_NUM_SPI_HOSTS; ++i) { + for (i = 0; i < OPENTITAN_NUM_SPI_HOSTS; ++i) { dev = DEVICE(&(s->spi_host[i])); if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi_host[i]), errp)) { return; From 29332994d8ebcbfad0748017c5151ed69e119212 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 25 Sep 2023 14:30:21 +1000 Subject: [PATCH 094/208] target/riscv: cpu: Fixup local variables shadowing Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Bugs love to hide in such code. Evidence: "[PATCH v3 1/7] migration/rdma: Fix save_page method to fail on polling error". This patch removes the local variable shadowing. Tested by adding: --extra-cflags='-Wshadow=local -Wno-error=shadow=local -Wno-error=shadow=compatible-local' To configure Signed-off-by: Alistair Francis Message-ID: <20230925043023.71448-3-alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza Signed-off-by: Markus Armbruster --- target/riscv/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index f227c7664e9c..4140899c5211 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -704,7 +704,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) CSR_MPMMASK, }; - for (int i = 0; i < ARRAY_SIZE(dump_csrs); ++i) { + for (i = 0; i < ARRAY_SIZE(dump_csrs); ++i) { int csrno = dump_csrs[i]; target_ulong val = 0; RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0); @@ -747,7 +747,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) CSR_VTYPE, CSR_VLENB, }; - for (int i = 0; i < ARRAY_SIZE(dump_rvv_csrs); ++i) { + for (i = 0; i < ARRAY_SIZE(dump_rvv_csrs); ++i) { int csrno = dump_rvv_csrs[i]; target_ulong val = 0; RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0); From f3f65c4022c4af793eecf8be9872510f83f98740 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 25 Sep 2023 14:30:22 +1000 Subject: [PATCH 095/208] target/riscv: vector_helper: Fixup local variables shadowing Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Bugs love to hide in such code. Evidence: "[PATCH v3 1/7] migration/rdma: Fix save_page method to fail on polling error". This patch removes the local variable shadowing. Tested by adding: --extra-cflags='-Wshadow=local -Wno-error=shadow=local -Wno-error=shadow=compatible-local' To configure Signed-off-by: Alistair Francis Message-ID: <20230925043023.71448-4-alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza Signed-off-by: Markus Armbruster --- target/riscv/vector_helper.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 3fb05cc3d6ee..cba02c13203a 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -516,7 +516,7 @@ vext_ldff(void *vd, void *v0, target_ulong base, k++; continue; } - target_ulong addr = base + ((i * nf + k) << log2_esz); + addr = base + ((i * nf + k) << log2_esz); ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra); k++; } @@ -4791,9 +4791,10 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint32_t total_elems = vext_get_total_elems(env, desc, esz); \ uint32_t vta = vext_vta(desc); \ uint32_t vma = vext_vma(desc); \ - target_ulong i_max, i; \ + target_ulong i_max, i_min, i; \ \ - i_max = MAX(MIN(s1 < vlmax ? vlmax - s1 : 0, vl), env->vstart); \ + i_min = MIN(s1 < vlmax ? vlmax - s1 : 0, vl); \ + i_max = MAX(i_min, env->vstart); \ for (i = env->vstart; i < i_max; ++i) { \ if (!vm && !vext_elem_mask(v0, i)) { \ /* set masked-off elements to 1s */ \ From 5567fa825ab9bdc4688308bea7816e2f969b65c3 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 25 Sep 2023 14:30:23 +1000 Subject: [PATCH 096/208] softmmu/device_tree: Fixup local variables shadowing Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Bugs love to hide in such code. Evidence: "[PATCH v3 1/7] migration/rdma: Fix save_page method to fail on polling error". This patch removes the local variable shadowing. Tested by adding: --extra-cflags='-Wshadow=local -Wno-error=shadow=local -Wno-error=shadow=compatible-local' To configure Signed-off-by: Alistair Francis Message-ID: <20230925043023.71448-5-alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza Signed-off-by: Markus Armbruster --- softmmu/device_tree.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c index 30aa3aea9fad..eb5166ca3608 100644 --- a/softmmu/device_tree.c +++ b/softmmu/device_tree.c @@ -418,9 +418,9 @@ int qemu_fdt_setprop_string_array(void *fdt, const char *node_path, } p = str = g_malloc0(total_len); for (i = 0; i < len; i++) { - int len = strlen(array[i]) + 1; - pstrcpy(p, len, array[i]); - p += len; + int offset = strlen(array[i]) + 1; + pstrcpy(p, offset, array[i]); + p += offset; } ret = qemu_fdt_setprop(fdt, node_path, prop, str, total_len); From f193d0bde70e1be004cc4aba5aaf3ac9c459d156 Mon Sep 17 00:00:00 2001 From: Klaus Jensen Date: Mon, 25 Sep 2023 08:05:05 +0200 Subject: [PATCH 097/208] hw/nvme: Clean up local variable shadowing in nvme_ns_init() Fix local variable shadowing in nvme_ns_init(). Reported-by: Markus Armbruster Signed-off-by: Klaus Jensen Message-ID: <20230925-fix-local-shadowing-v1-1-3a1172132377@samsung.com> Reviewed-by: Jesper Wendel Devantier Signed-off-by: Markus Armbruster --- hw/nvme/ns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 44aba8f4d9cf..0eabcf5cf500 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -107,7 +107,7 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp) ns->pif = ns->params.pif; - static const NvmeLBAF lbaf[16] = { + static const NvmeLBAF defaults[16] = { [0] = { .ds = 9 }, [1] = { .ds = 9, .ms = 8 }, [2] = { .ds = 9, .ms = 16 }, @@ -120,7 +120,7 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp) ns->nlbaf = 8; - memcpy(&id_ns->lbaf, &lbaf, sizeof(lbaf)); + memcpy(&id_ns->lbaf, &defaults, sizeof(defaults)); for (i = 0; i < ns->nlbaf; i++) { NvmeLBAF *lbaf = &id_ns->lbaf[i]; From 4dba9141f97e66fdd920df37c4aa7b2ffe0d6a4a Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Mon, 25 Sep 2023 10:44:55 +0200 Subject: [PATCH 098/208] disas/m68k: clean up local variable shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix following warnings .../disas/m68k.c: In function ‘print_insn_arg’: .../disas/m68k.c:1635:13: warning: declaration of ‘val’ shadows a previous local [-Wshadow=compatible-local] 1635 | int val = fetch_arg (buffer, place, 5, info); | ^~~ .../disas/m68k.c:1093:7: note: shadowed declaration is here 1093 | int val = 0; | ^~~ Signed-off-by: Laurent Vivier Message-ID: <20230925084455.395150-1-laurent@vivier.eu> Reviewed-by: Thomas Huth Signed-off-by: Markus Armbruster --- disas/m68k.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/disas/m68k.c b/disas/m68k.c index aefaecfbd6cb..1f16e295ab41 100644 --- a/disas/m68k.c +++ b/disas/m68k.c @@ -1632,10 +1632,10 @@ print_insn_arg (const char *d, case '2': case '3': { - int val = fetch_arg (buffer, place, 5, info); + int reg = fetch_arg (buffer, place, 5, info); const char *name = 0; - switch (val) + switch (reg) { case 2: name = "%tt0"; break; case 3: name = "%tt1"; break; @@ -1655,12 +1655,12 @@ print_insn_arg (const char *d, int break_reg = ((buffer[3] >> 2) & 7); (*info->fprintf_func) - (info->stream, val == 0x1c ? "%%bad%d" : "%%bac%d", + (info->stream, reg == 0x1c ? "%%bad%d" : "%%bac%d", break_reg); } break; default: - (*info->fprintf_func) (info->stream, "", val); + (*info->fprintf_func) (info->stream, "", reg); } if (name) (*info->fprintf_func) (info->stream, "%s", name); From 71d3612401b614bc64a00fafa8dd930a5672b782 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 9 Jun 2023 00:49:08 +0200 Subject: [PATCH 099/208] migration-test: Create kvm_opts So arch_dirty_ring option becomes one option like the others. Reviewed-by: Peter Xu Message-ID: <20230608224943.3877-8-quintela@redhat.com> Signed-off-by: Juan Quintela --- tests/qtest/migration-test.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 1b43df5ca7c3..bde553730e9b 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -710,6 +710,7 @@ static int test_migrate_start(QTestState **from, QTestState **to, g_autofree char *bootpath = NULL; g_autofree char *shmem_opts = NULL; g_autofree char *shmem_path = NULL; + const char *kvm_opts = NULL; const char *arch = qtest_get_arch(); const char *memory_size; @@ -785,13 +786,16 @@ static int test_migrate_start(QTestState **from, QTestState **to, shmem_opts = g_strdup(""); } + if (args->use_dirty_ring) { + kvm_opts = ",dirty-ring-size=4096"; + } + cmd_source = g_strdup_printf("-accel kvm%s -accel tcg " "-name source,debug-threads=on " "-m %s " "-serial file:%s/src_serial " "%s %s %s %s %s", - args->use_dirty_ring ? - ",dirty-ring-size=4096" : "", + kvm_opts ? kvm_opts : "", memory_size, tmpfs, arch_opts ? arch_opts : "", arch_source ? arch_source : "", @@ -811,8 +815,7 @@ static int test_migrate_start(QTestState **from, QTestState **to, "-serial file:%s/dest_serial " "-incoming %s " "%s %s %s %s %s", - args->use_dirty_ring ? - ",dirty-ring-size=4096" : "", + kvm_opts ? kvm_opts : "", memory_size, tmpfs, uri, arch_opts ? arch_opts : "", arch_target ? arch_target : "", From 877cec63d77058c27230b33643508dfeb84d8021 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 9 Jun 2023 00:49:09 +0200 Subject: [PATCH 100/208] migration-test: bootpath is the same for all tests and for all archs So just make it a global variable. Reviewed-by: Peter Xu Message-ID: <20230608224943.3877-9-quintela@redhat.com> Signed-off-by: Juan Quintela --- tests/qtest/migration-test.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index bde553730e9b..e191f66e546a 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -116,6 +116,7 @@ static bool ufd_version_check(void) #endif static char *tmpfs; +static char *bootpath; /* The boot file modifies memory area in [start_address, end_address) * repeatedly. It outputs a 'B' at a fixed rate while it's still running. @@ -124,7 +125,7 @@ static char *tmpfs; #include "tests/migration/aarch64/a-b-kernel.h" #include "tests/migration/s390x/a-b-bios.h" -static void init_bootfile(const char *bootpath, void *content, size_t len) +static void init_bootfile(void *content, size_t len) { FILE *bootfile = fopen(bootpath, "wb"); @@ -707,7 +708,6 @@ static int test_migrate_start(QTestState **from, QTestState **to, g_autofree gchar *cmd_source = NULL; g_autofree gchar *cmd_target = NULL; const gchar *ignore_stderr; - g_autofree char *bootpath = NULL; g_autofree char *shmem_opts = NULL; g_autofree char *shmem_path = NULL; const char *kvm_opts = NULL; @@ -723,17 +723,16 @@ static int test_migrate_start(QTestState **from, QTestState **to, got_src_stop = false; got_dst_resume = false; - bootpath = g_strdup_printf("%s/bootsect", tmpfs); if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { /* the assembled x86 boot sector should be exactly one sector large */ assert(sizeof(x86_bootsect) == 512); - init_bootfile(bootpath, x86_bootsect, sizeof(x86_bootsect)); + init_bootfile(x86_bootsect, sizeof(x86_bootsect)); memory_size = "150M"; arch_opts = g_strdup_printf("-drive file=%s,format=raw", bootpath); start_address = X86_TEST_MEM_START; end_address = X86_TEST_MEM_END; } else if (g_str_equal(arch, "s390x")) { - init_bootfile(bootpath, s390x_elf, sizeof(s390x_elf)); + init_bootfile(s390x_elf, sizeof(s390x_elf)); memory_size = "128M"; arch_opts = g_strdup_printf("-bios %s", bootpath); start_address = S390_TEST_MEM_START; @@ -748,7 +747,7 @@ static int test_migrate_start(QTestState **from, QTestState **to, "until'", end_address, start_address); arch_opts = g_strdup("-nodefaults -machine vsmt=8"); } else if (strcmp(arch, "aarch64") == 0) { - init_bootfile(bootpath, aarch64_kernel, sizeof(aarch64_kernel)); + init_bootfile(aarch64_kernel, sizeof(aarch64_kernel)); memory_size = "150M"; arch_opts = g_strdup_printf("-machine virt,gic-version=max -cpu max " "-kernel %s", bootpath); @@ -866,7 +865,6 @@ static void test_migrate_end(QTestState *from, QTestState *to, bool test_dest) qtest_quit(to); - cleanup("bootsect"); cleanup("migsocket"); cleanup("src_serial"); cleanup("dest_serial"); @@ -2629,12 +2627,10 @@ static QTestState *dirtylimit_start_vm(void) QTestState *vm = NULL; g_autofree gchar *cmd = NULL; const char *arch = qtest_get_arch(); - g_autofree char *bootpath = NULL; assert((strcmp(arch, "x86_64") == 0)); - bootpath = g_strdup_printf("%s/bootsect", tmpfs); assert(sizeof(x86_bootsect) == 512); - init_bootfile(bootpath, x86_bootsect, sizeof(x86_bootsect)); + init_bootfile(x86_bootsect, sizeof(x86_bootsect)); cmd = g_strdup_printf("-accel kvm,dirty-ring-size=4096 " "-name dirtylimit-test,debug-threads=on " @@ -2650,7 +2646,6 @@ static QTestState *dirtylimit_start_vm(void) static void dirtylimit_stop_vm(QTestState *vm) { qtest_quit(vm); - cleanup("bootsect"); cleanup("vm_serial"); } @@ -2812,6 +2807,7 @@ int main(int argc, char **argv) g_get_tmp_dir(), err->message); } g_assert(tmpfs); + bootpath = g_strdup_printf("%s/bootsect", tmpfs); module_call_init(MODULE_INIT_QOM); @@ -2959,6 +2955,8 @@ int main(int argc, char **argv) g_assert_cmpint(ret, ==, 0); + cleanup("bootsect"); + g_free(bootpath); ret = rmdir(tmpfs); if (ret != 0) { g_test_message("unable to rmdir: path (%s): %s", From 0c690d3e2a3eb73a6c27afb66ec87534c1259bae Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 9 Jun 2023 00:49:10 +0200 Subject: [PATCH 101/208] migration-test: Add bootfile_create/delete() functions The bootsector code is read only from the guest (otherwise we are going to have problems with it being read from both source and destination). Create a single copy for all the tests. Reviewed-by: Peter Xu Message-ID: <20230608224943.3877-10-quintela@redhat.com> Signed-off-by: Juan Quintela --- tests/qtest/migration-test.c | 50 ++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index e191f66e546a..f6012493916f 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -125,14 +125,47 @@ static char *bootpath; #include "tests/migration/aarch64/a-b-kernel.h" #include "tests/migration/s390x/a-b-bios.h" -static void init_bootfile(void *content, size_t len) +static void bootfile_create(char *dir) { + const char *arch = qtest_get_arch(); + unsigned char *content; + size_t len; + + bootpath = g_strdup_printf("%s/bootsect", dir); + if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { + /* the assembled x86 boot sector should be exactly one sector large */ + g_assert(sizeof(x86_bootsect) == 512); + content = x86_bootsect; + len = sizeof(x86_bootsect); + } else if (g_str_equal(arch, "s390x")) { + content = s390x_elf; + len = sizeof(s390x_elf); + } else if (strcmp(arch, "ppc64") == 0) { + /* + * sane architectures can be programmed at the boot prompt + */ + return; + } else if (strcmp(arch, "aarch64") == 0) { + content = aarch64_kernel; + len = sizeof(aarch64_kernel); + g_assert(sizeof(aarch64_kernel) <= ARM_TEST_MAX_KERNEL_SIZE); + } else { + g_assert_not_reached(); + } + FILE *bootfile = fopen(bootpath, "wb"); g_assert_cmpint(fwrite(content, len, 1, bootfile), ==, 1); fclose(bootfile); } +static void bootfile_delete(void) +{ + unlink(bootpath); + g_free(bootpath); + bootpath = NULL; +} + /* * Wait for some output in the serial output file, * we get an 'A' followed by an endless string of 'B's @@ -724,15 +757,11 @@ static int test_migrate_start(QTestState **from, QTestState **to, got_src_stop = false; got_dst_resume = false; if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { - /* the assembled x86 boot sector should be exactly one sector large */ - assert(sizeof(x86_bootsect) == 512); - init_bootfile(x86_bootsect, sizeof(x86_bootsect)); memory_size = "150M"; arch_opts = g_strdup_printf("-drive file=%s,format=raw", bootpath); start_address = X86_TEST_MEM_START; end_address = X86_TEST_MEM_END; } else if (g_str_equal(arch, "s390x")) { - init_bootfile(s390x_elf, sizeof(s390x_elf)); memory_size = "128M"; arch_opts = g_strdup_printf("-bios %s", bootpath); start_address = S390_TEST_MEM_START; @@ -747,14 +776,11 @@ static int test_migrate_start(QTestState **from, QTestState **to, "until'", end_address, start_address); arch_opts = g_strdup("-nodefaults -machine vsmt=8"); } else if (strcmp(arch, "aarch64") == 0) { - init_bootfile(aarch64_kernel, sizeof(aarch64_kernel)); memory_size = "150M"; arch_opts = g_strdup_printf("-machine virt,gic-version=max -cpu max " "-kernel %s", bootpath); start_address = ARM_TEST_MEM_START; end_address = ARM_TEST_MEM_END; - - g_assert(sizeof(aarch64_kernel) <= ARM_TEST_MAX_KERNEL_SIZE); } else { g_assert_not_reached(); } @@ -2629,9 +2655,6 @@ static QTestState *dirtylimit_start_vm(void) const char *arch = qtest_get_arch(); assert((strcmp(arch, "x86_64") == 0)); - assert(sizeof(x86_bootsect) == 512); - init_bootfile(x86_bootsect, sizeof(x86_bootsect)); - cmd = g_strdup_printf("-accel kvm,dirty-ring-size=4096 " "-name dirtylimit-test,debug-threads=on " "-m 150M -smp 1 " @@ -2807,7 +2830,7 @@ int main(int argc, char **argv) g_get_tmp_dir(), err->message); } g_assert(tmpfs); - bootpath = g_strdup_printf("%s/bootsect", tmpfs); + bootfile_create(tmpfs); module_call_init(MODULE_INIT_QOM); @@ -2955,8 +2978,7 @@ int main(int argc, char **argv) g_assert_cmpint(ret, ==, 0); - cleanup("bootsect"); - g_free(bootpath); + bootfile_delete(); ret = rmdir(tmpfs); if (ret != 0) { g_test_message("unable to rmdir: path (%s): %s", From 22d3c6e16c69ea581eef6f7ff8ebb2e63107d3f5 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 9 Jun 2023 00:49:11 +0200 Subject: [PATCH 102/208] migration-test: dirtylimit checks for x86_64 arch before So no need to assert we are in x86_64. Once there, refactor the function to remove useless variables. Reviewed-by: Peter Xu Message-ID: <20230608224943.3877-11-quintela@redhat.com> Signed-off-by: Juan Quintela --- tests/qtest/migration-test.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index f6012493916f..334648ae199b 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -2651,10 +2651,7 @@ static int64_t get_limit_rate(QTestState *who) static QTestState *dirtylimit_start_vm(void) { QTestState *vm = NULL; - g_autofree gchar *cmd = NULL; - const char *arch = qtest_get_arch(); - - assert((strcmp(arch, "x86_64") == 0)); + g_autofree gchar * cmd = g_strdup_printf("-accel kvm,dirty-ring-size=4096 " "-name dirtylimit-test,debug-threads=on " "-m 150M -smp 1 " From 0368ace8f9eb24c5959466db352e4c4afc734954 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 9 Jun 2023 00:49:04 +0200 Subject: [PATCH 103/208] migration-test: simplify shmem_opts handling Reviewed-by: Peter Xu Message-ID: <20230608224943.3877-4-quintela@redhat.com> Signed-off-by: Juan Quintela --- tests/qtest/migration-test.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 334648ae199b..46f1c275a259 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -806,9 +806,6 @@ static int test_migrate_start(QTestState **from, QTestState **to, "-object memory-backend-file,id=mem0,size=%s" ",mem-path=%s,share=on -numa node,memdev=mem0", memory_size, shmem_path); - } else { - shmem_path = NULL; - shmem_opts = g_strdup(""); } if (args->use_dirty_ring) { @@ -824,7 +821,7 @@ static int test_migrate_start(QTestState **from, QTestState **to, memory_size, tmpfs, arch_opts ? arch_opts : "", arch_source ? arch_source : "", - shmem_opts, + shmem_opts ? shmem_opts : "", args->opts_source ? args->opts_source : "", ignore_stderr); if (!args->only_target) { @@ -844,7 +841,7 @@ static int test_migrate_start(QTestState **from, QTestState **to, memory_size, tmpfs, uri, arch_opts ? arch_opts : "", arch_target ? arch_target : "", - shmem_opts, + shmem_opts ? shmem_opts : "", args->opts_target ? args->opts_target : "", ignore_stderr); *to = qtest_init(cmd_target); From f4e1b613362e51e205081a60b94f157c16acdca3 Mon Sep 17 00:00:00 2001 From: Tejus GK Date: Wed, 21 Jun 2023 13:09:40 +0000 Subject: [PATCH 104/208] migration: Refactor repeated call of yank_unregister_instance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the function qmp_migrate(), yank_unregister_instance() gets called twice which isn't required. Hence, refactoring it so that it gets called during the local_error cleanup. Reviewed-by: Daniel P. Berrangé Reviewed-by: Juan Quintela Acked-by: Peter Xu Signed-off-by: Tejus GK Message-ID: <20230621130940.178659-3-tejus.gk@nutanix.com> Signed-off-by: Juan Quintela --- migration/migration.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index e2ed85b5be74..6d3cf5d5cd89 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1703,15 +1703,11 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, } else if (strstart(uri, "fd:", &p)) { fd_start_outgoing_migration(s, p, &local_err); } else { - if (!resume_requested) { - yank_unregister_instance(MIGRATION_YANK_INSTANCE); - } error_setg(&local_err, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol"); migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED); block_cleanup_parameters(); - return; } if (local_err) { From f16ecfa9f9c147168630422a6f4a4c0eddfbe574 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 30 May 2023 20:39:24 +0200 Subject: [PATCH 105/208] migration: Use qemu_file_transferred_noflush() for block migration. We only care about the amount of bytes transferred. Flushing is done by the system somewhere else. Reviewed-by: Fabiano Rosas Signed-off-by: Juan Quintela Message-ID: <20230530183941.7223-4-quintela@redhat.com> Signed-off-by: Juan Quintela --- migration/block.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/migration/block.c b/migration/block.c index 86c2256a2bfb..26c10c0a0cb0 100644 --- a/migration/block.c +++ b/migration/block.c @@ -755,7 +755,7 @@ static int block_save_setup(QEMUFile *f, void *opaque) static int block_save_iterate(QEMUFile *f, void *opaque) { int ret; - uint64_t last_bytes = qemu_file_transferred(f); + uint64_t last_bytes = qemu_file_transferred_noflush(f); trace_migration_block_save("iterate", block_mig_state.submitted, block_mig_state.transferred); @@ -807,7 +807,7 @@ static int block_save_iterate(QEMUFile *f, void *opaque) } qemu_put_be64(f, BLK_MIG_FLAG_EOS); - uint64_t delta_bytes = qemu_file_transferred(f) - last_bytes; + uint64_t delta_bytes = qemu_file_transferred_noflush(f) - last_bytes; return (delta_bytes > 0); } From 67c31c9c1af1bb8f7df8275cc8731629e2690f89 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 15 May 2023 21:57:03 +0200 Subject: [PATCH 106/208] migration: Don't abuse qemu_file transferred for RDMA Just create a variable for it, the same way that multifd does. This way it is safe to use for other thread, etc, etc. Reviewed-by: Leonardo Bras Signed-off-by: Juan Quintela Message-Id: <20230515195709.63843-11-quintela@redhat.com> --- migration/migration-stats.c | 5 +++-- migration/migration-stats.h | 4 ++++ migration/rdma.c | 22 ++++++++++++++++++++-- migration/trace-events | 2 +- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/migration/migration-stats.c b/migration/migration-stats.c index 095d6d75bb17..84e11e6dd884 100644 --- a/migration/migration-stats.c +++ b/migration/migration-stats.c @@ -61,8 +61,9 @@ void migration_rate_reset(QEMUFile *f) uint64_t migration_transferred_bytes(QEMUFile *f) { uint64_t multifd = stat64_get(&mig_stats.multifd_bytes); + uint64_t rdma = stat64_get(&mig_stats.rdma_bytes); uint64_t qemu_file = qemu_file_transferred(f); - trace_migration_transferred_bytes(qemu_file, multifd); - return qemu_file + multifd; + trace_migration_transferred_bytes(qemu_file, multifd, rdma); + return qemu_file + multifd + rdma; } diff --git a/migration/migration-stats.h b/migration/migration-stats.h index ac2260e987c0..2358caad6382 100644 --- a/migration/migration-stats.h +++ b/migration/migration-stats.h @@ -89,6 +89,10 @@ typedef struct { * Maximum amount of data we can send in a cycle. */ Stat64 rate_limit_max; + /* + * Number of bytes sent through RDMA. + */ + Stat64 rdma_bytes; /* * Total number of bytes transferred. */ diff --git a/migration/rdma.c b/migration/rdma.c index a2a3db35b1d1..2a3c784328e7 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -2122,9 +2122,18 @@ static int qemu_rdma_write_one(QEMUFile *f, RDMAContext *rdma, return -EIO; } + /* + * TODO: Here we are sending something, but we are not + * accounting for anything transferred. The following is wrong: + * + * stat64_add(&mig_stats.rdma_bytes, sge.length); + * + * because we are using some kind of compression. I + * would think that head.len would be the more similar + * thing to a correct value. + */ stat64_add(&mig_stats.zero_pages, sge.length / qemu_target_page_size()); - return 1; } @@ -2232,8 +2241,17 @@ static int qemu_rdma_write_one(QEMUFile *f, RDMAContext *rdma, set_bit(chunk, block->transit_bitmap); stat64_add(&mig_stats.normal_pages, sge.length / qemu_target_page_size()); + /* + * We are adding to transferred the amount of data written, but no + * overhead at all. I will asume that RDMA is magicaly and don't + * need to transfer (at least) the addresses where it wants to + * write the pages. Here it looks like it should be something + * like: + * sizeof(send_wr) + sge.length + * but this being RDMA, who knows. + */ + stat64_add(&mig_stats.rdma_bytes, sge.length); ram_transferred_add(sge.length); - qemu_file_credit_transfer(f, sge.length); rdma->total_writes++; return 0; diff --git a/migration/trace-events b/migration/trace-events index 4666f19325e7..63483732ce81 100644 --- a/migration/trace-events +++ b/migration/trace-events @@ -191,7 +191,7 @@ process_incoming_migration_co_postcopy_end_main(void) "" postcopy_preempt_enabled(bool value) "%d" # migration-stats -migration_transferred_bytes(uint64_t qemu_file, uint64_t multifd) "qemu_file %" PRIu64 " multifd %" PRIu64 +migration_transferred_bytes(uint64_t qemu_file, uint64_t multifd, uint64_t rdma) "qemu_file %" PRIu64 " multifd %" PRIu64 " RDMA %" PRIu64 # channel.c migration_set_incoming_channel(void *ioc, const char *ioctype) "ioc=%p ioctype=%s" From 19df4f3226c0f3e80291a40aec3c9c459dadfdf4 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 15 May 2023 21:57:04 +0200 Subject: [PATCH 107/208] migration/RDMA: It is accounting for zero/normal pages in two places Remove the one in control_save_page(). Reviewed-by: Leonardo Bras Signed-off-by: Juan Quintela Message-Id: <20230515195709.63843-12-quintela@redhat.com> --- migration/ram.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/migration/ram.c b/migration/ram.c index 9040d66e615e..f2c5b0791933 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1204,13 +1204,6 @@ static bool control_save_page(PageSearchStatus *pss, RAMBlock *block, if (ret == RAM_SAVE_CONTROL_DELAYED) { return true; } - - if (bytes_xmit > 0) { - stat64_add(&mig_stats.normal_pages, 1); - } else if (bytes_xmit == 0) { - stat64_add(&mig_stats.zero_pages, 1); - } - return true; } From e33780351ceb8317dccec143e722ae8434d58c34 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 15 May 2023 21:57:05 +0200 Subject: [PATCH 108/208] migration/rdma: Remove QEMUFile parameter when not used Reviewed-by: Leonardo Bras Signed-off-by: Juan Quintela Message-Id: <20230515195709.63843-13-quintela@redhat.com> --- migration/rdma.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/migration/rdma.c b/migration/rdma.c index 2a3c784328e7..9007261b5ccb 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -2027,7 +2027,7 @@ static int qemu_rdma_exchange_recv(RDMAContext *rdma, RDMAControlHeader *head, * If we're using dynamic registration on the dest-side, we have to * send a registration command first. */ -static int qemu_rdma_write_one(QEMUFile *f, RDMAContext *rdma, +static int qemu_rdma_write_one(RDMAContext *rdma, int current_index, uint64_t current_addr, uint64_t length) { @@ -2263,7 +2263,7 @@ static int qemu_rdma_write_one(QEMUFile *f, RDMAContext *rdma, * We support sending out multiple chunks at the same time. * Not all of them need to get signaled in the completion queue. */ -static int qemu_rdma_write_flush(QEMUFile *f, RDMAContext *rdma) +static int qemu_rdma_write_flush(RDMAContext *rdma) { int ret; @@ -2271,7 +2271,7 @@ static int qemu_rdma_write_flush(QEMUFile *f, RDMAContext *rdma) return 0; } - ret = qemu_rdma_write_one(f, rdma, + ret = qemu_rdma_write_one(rdma, rdma->current_index, rdma->current_addr, rdma->current_length); if (ret < 0) { @@ -2344,7 +2344,7 @@ static inline int qemu_rdma_buffer_mergable(RDMAContext *rdma, * and only require that a batch gets acknowledged in the completion * queue instead of each individual chunk. */ -static int qemu_rdma_write(QEMUFile *f, RDMAContext *rdma, +static int qemu_rdma_write(RDMAContext *rdma, uint64_t block_offset, uint64_t offset, uint64_t len) { @@ -2355,7 +2355,7 @@ static int qemu_rdma_write(QEMUFile *f, RDMAContext *rdma, /* If we cannot merge it, we flush the current buffer first. */ if (!qemu_rdma_buffer_mergable(rdma, current_addr, len)) { - ret = qemu_rdma_write_flush(f, rdma); + ret = qemu_rdma_write_flush(rdma); if (ret) { return ret; } @@ -2377,7 +2377,7 @@ static int qemu_rdma_write(QEMUFile *f, RDMAContext *rdma, /* flush it if buffer is too large */ if (rdma->current_length >= RDMA_MERGE_MAX) { - return qemu_rdma_write_flush(f, rdma); + return qemu_rdma_write_flush(rdma); } return 0; @@ -2798,7 +2798,6 @@ static ssize_t qio_channel_rdma_writev(QIOChannel *ioc, Error **errp) { QIOChannelRDMA *rioc = QIO_CHANNEL_RDMA(ioc); - QEMUFile *f = rioc->file; RDMAContext *rdma; int ret; ssize_t done = 0; @@ -2819,7 +2818,7 @@ static ssize_t qio_channel_rdma_writev(QIOChannel *ioc, * Push out any writes that * we're queued up for VM's ram. */ - ret = qemu_rdma_write_flush(f, rdma); + ret = qemu_rdma_write_flush(rdma); if (ret < 0) { rdma->error_state = ret; error_setg(errp, "qemu_rdma_write_flush returned %d", ret); @@ -2958,11 +2957,11 @@ static ssize_t qio_channel_rdma_readv(QIOChannel *ioc, /* * Block until all the outstanding chunks have been delivered by the hardware. */ -static int qemu_rdma_drain_cq(QEMUFile *f, RDMAContext *rdma) +static int qemu_rdma_drain_cq(RDMAContext *rdma) { int ret; - if (qemu_rdma_write_flush(f, rdma) < 0) { + if (qemu_rdma_write_flush(rdma) < 0) { return -EIO; } @@ -3273,7 +3272,7 @@ static size_t qemu_rdma_save_page(QEMUFile *f, * is full, or the page doesn't belong to the current chunk, * an actual RDMA write will occur and a new chunk will be formed. */ - ret = qemu_rdma_write(f, rdma, block_offset, offset, size); + ret = qemu_rdma_write(rdma, block_offset, offset, size); if (ret < 0) { error_report("rdma migration: write error! %d", ret); goto err; @@ -3928,7 +3927,7 @@ static int qemu_rdma_registration_stop(QEMUFile *f, CHECK_ERROR_STATE(); qemu_fflush(f); - ret = qemu_rdma_drain_cq(f, rdma); + ret = qemu_rdma_drain_cq(rdma); if (ret < 0) { goto err; From 2ebe5d4d5aa4d11f02a2d52fa398a52a6a0dc2ee Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 15 May 2023 21:57:06 +0200 Subject: [PATCH 109/208] migration/rdma: Don't use imaginary transfers RDMA protocol is completely asynchronous, so in qemu_rdma_save_page() they "invent" that a byte has been transferred. And then they call qemu_file_credit_transfer() and ram_transferred_add() with that byte. Just remove that calls as nothing has been sent. Reviewed-by: Leonardo Bras Signed-off-by: Juan Quintela Message-Id: <20230515195709.63843-14-quintela@redhat.com> --- migration/qemu-file.c | 5 +---- migration/ram.c | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/migration/qemu-file.c b/migration/qemu-file.c index 19c33c998588..e53ff2dd863a 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -332,13 +332,10 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset, if (ret != RAM_SAVE_CONTROL_DELAYED && ret != RAM_SAVE_CONTROL_NOT_SUPP) { - if (bytes_sent && *bytes_sent > 0) { - qemu_file_credit_transfer(f, *bytes_sent); - } else if (ret < 0) { + if (ret < 0) { qemu_file_set_error(f, ret); } } - return ret; } diff --git a/migration/ram.c b/migration/ram.c index f2c5b0791933..c6238f7a8b3e 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1197,7 +1197,6 @@ static bool control_save_page(PageSearchStatus *pss, RAMBlock *block, } if (bytes_xmit) { - ram_transferred_add(bytes_xmit); *pages = 1; } From 9f51fe92392f601a177687bef01a545298cb47e1 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 15 May 2023 21:57:07 +0200 Subject: [PATCH 110/208] migration: Remove unused qemu_file_credit_transfer() After this change, nothing abuses QEMUFile to account for data transferrefd during migration. Reviewed-by: Leonardo Bras Signed-off-by: Juan Quintela Message-Id: <20230515195709.63843-15-quintela@redhat.com> --- migration/qemu-file.c | 5 ----- migration/qemu-file.h | 8 -------- 2 files changed, 13 deletions(-) diff --git a/migration/qemu-file.c b/migration/qemu-file.c index e53ff2dd863a..5c43fa34e7ea 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -397,11 +397,6 @@ static ssize_t coroutine_mixed_fn qemu_fill_buffer(QEMUFile *f) return len; } -void qemu_file_credit_transfer(QEMUFile *f, size_t size) -{ - f->total_transferred += size; -} - /** Closes the file * * Returns negative error value if any error happened on previous operations or diff --git a/migration/qemu-file.h b/migration/qemu-file.h index 47015f520117..57b00c85625f 100644 --- a/migration/qemu-file.h +++ b/migration/qemu-file.h @@ -119,14 +119,6 @@ bool qemu_file_buffer_empty(QEMUFile *file); */ int coroutine_mixed_fn qemu_peek_byte(QEMUFile *f, int offset); void qemu_file_skip(QEMUFile *f, int size); -/* - * qemu_file_credit_transfer: - * - * Report on a number of bytes that have been transferred - * out of band from the main file object I/O methods. This - * accounting information tracks the total migration traffic. - */ -void qemu_file_credit_transfer(QEMUFile *f, size_t size); int qemu_file_get_error_obj_any(QEMUFile *f1, QEMUFile *f2, Error **errp); void qemu_file_set_error_obj(QEMUFile *f, int ret, Error *err); void qemu_file_set_error(QEMUFile *f, int ret); From 9c53d369e5903375a2e3358f739be77dcb8dae49 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 15 May 2023 21:57:08 +0200 Subject: [PATCH 111/208] migration/rdma: Simplify the function that saves a page When we sent a page through QEMUFile hooks (RDMA) there are three posiblities: - We are not using RDMA. return RAM_SAVE_CONTROL_DELAYED and control_save_page() returns false to let anything else to proceed. - There is one error but we are using RDMA. Then we return a negative value, control_save_page() needs to return true. - Everything goes well and RDMA start the sent of the page asynchronously. It returns RAM_SAVE_CONTROL_DELAYED and we need to return 1 for ram_save_page_legacy. Clear? I know, I know, the interface is as bad as it gets. I think that now it is a bit clearer, but this needs to be done some other way. Reviewed-by: Leonardo Bras Signed-off-by: Juan Quintela Message-Id: <20230515195709.63843-16-quintela@redhat.com> --- migration/qemu-file.c | 12 ++++++------ migration/qemu-file.h | 14 ++++++-------- migration/ram.c | 10 +++------- migration/rdma.c | 19 +++---------------- 4 files changed, 18 insertions(+), 37 deletions(-) diff --git a/migration/qemu-file.c b/migration/qemu-file.c index 5c43fa34e7ea..5e8207dae4e6 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -322,14 +322,14 @@ void ram_control_load_hook(QEMUFile *f, uint64_t flags, void *data) } } -size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset, - ram_addr_t offset, size_t size, - uint64_t *bytes_sent) +int ram_control_save_page(QEMUFile *f, ram_addr_t block_offset, + ram_addr_t offset, size_t size) { if (f->hooks && f->hooks->save_page) { - int ret = f->hooks->save_page(f, block_offset, - offset, size, bytes_sent); - + int ret = f->hooks->save_page(f, block_offset, offset, size); + /* + * RAM_SAVE_CONTROL_* are negative values + */ if (ret != RAM_SAVE_CONTROL_DELAYED && ret != RAM_SAVE_CONTROL_NOT_SUPP) { if (ret < 0) { diff --git a/migration/qemu-file.h b/migration/qemu-file.h index 57b00c85625f..03e718c264e7 100644 --- a/migration/qemu-file.h +++ b/migration/qemu-file.h @@ -49,11 +49,10 @@ typedef int (QEMURamHookFunc)(QEMUFile *f, uint64_t flags, void *data); * This function allows override of where the RAM page * is saved (such as RDMA, for example.) */ -typedef size_t (QEMURamSaveFunc)(QEMUFile *f, - ram_addr_t block_offset, - ram_addr_t offset, - size_t size, - uint64_t *bytes_sent); +typedef int (QEMURamSaveFunc)(QEMUFile *f, + ram_addr_t block_offset, + ram_addr_t offset, + size_t size); typedef struct QEMUFileHooks { QEMURamHookFunc *before_ram_iterate; @@ -142,9 +141,8 @@ void ram_control_load_hook(QEMUFile *f, uint64_t flags, void *data); #define RAM_SAVE_CONTROL_NOT_SUPP -1000 #define RAM_SAVE_CONTROL_DELAYED -2000 -size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset, - ram_addr_t offset, size_t size, - uint64_t *bytes_sent); +int ram_control_save_page(QEMUFile *f, ram_addr_t block_offset, + ram_addr_t offset, size_t size); QIOChannel *qemu_file_get_ioc(QEMUFile *file); #endif diff --git a/migration/ram.c b/migration/ram.c index c6238f7a8b3e..99cff591a39a 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1186,23 +1186,19 @@ static int save_zero_page(PageSearchStatus *pss, QEMUFile *f, RAMBlock *block, static bool control_save_page(PageSearchStatus *pss, RAMBlock *block, ram_addr_t offset, int *pages) { - uint64_t bytes_xmit = 0; int ret; - *pages = -1; ret = ram_control_save_page(pss->pss_channel, block->offset, offset, - TARGET_PAGE_SIZE, &bytes_xmit); + TARGET_PAGE_SIZE); if (ret == RAM_SAVE_CONTROL_NOT_SUPP) { return false; } - if (bytes_xmit) { - *pages = 1; - } - if (ret == RAM_SAVE_CONTROL_DELAYED) { + *pages = 1; return true; } + *pages = ret; return true; } diff --git a/migration/rdma.c b/migration/rdma.c index 9007261b5ccb..5748c9045b19 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -3240,13 +3240,12 @@ qio_channel_rdma_shutdown(QIOChannel *ioc, * * @size : Number of bytes to transfer * - * @bytes_sent : User-specificed pointer to indicate how many bytes were + * @pages_sent : User-specificed pointer to indicate how many pages were * sent. Usually, this will not be more than a few bytes of * the protocol because most transfers are sent asynchronously. */ -static size_t qemu_rdma_save_page(QEMUFile *f, - ram_addr_t block_offset, ram_addr_t offset, - size_t size, uint64_t *bytes_sent) +static int qemu_rdma_save_page(QEMUFile *f, ram_addr_t block_offset, + ram_addr_t offset, size_t size) { QIOChannelRDMA *rioc = QIO_CHANNEL_RDMA(qemu_file_get_ioc(f)); RDMAContext *rdma; @@ -3278,18 +3277,6 @@ static size_t qemu_rdma_save_page(QEMUFile *f, goto err; } - /* - * We always return 1 bytes because the RDMA - * protocol is completely asynchronous. We do not yet know - * whether an identified chunk is zero or not because we're - * waiting for other pages to potentially be merged with - * the current chunk. So, we have to call qemu_update_position() - * later on when the actual write occurs. - */ - if (bytes_sent) { - *bytes_sent = 1; - } - /* * Drain the Completion Queue if possible, but do not block, * just poll. From ce43e84260a7d6250bf212aac958d73cfa1ca704 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 28 Sep 2023 09:53:55 +0200 Subject: [PATCH 112/208] Makefile: build plugins before running TCG tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add back test-plugins and, after making sure it is always defined, do so unconditionally. Reported-by: Alex Bennée Fixes: 2c13c574418 ("configure, meson: move --enable-plugins to meson", 2023-09-07) Reviewed-by: Alex Bennée Tested-by: Alex Bennée Signed-off-by: Paolo Bonzini --- tests/Makefile.include | 2 +- tests/meson.build | 5 +---- tests/plugin/meson.build | 18 ++++++++++++------ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/Makefile.include b/tests/Makefile.include index 389874265944..dab1989a0710 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -73,7 +73,7 @@ $(TCG_TESTS_TARGETS:%=distclean-tcg-tests-%): distclean-tcg-tests-%: build-tcg: $(BUILD_TCG_TARGET_RULES) .PHONY: check-tcg -.ninja-goals.check-tcg = all +.ninja-goals.check-tcg = all test-plugins check-tcg: $(RUN_TCG_TARGET_RULES) .PHONY: clean-tcg diff --git a/tests/meson.build b/tests/meson.build index debaa4505eb7..9996a293fbb5 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -80,10 +80,7 @@ if 'CONFIG_TCG' in config_all subdir('fp') endif -if get_option('plugins') - subdir('plugin') -endif - +subdir('plugin') subdir('unit') subdir('qapi-schema') subdir('qtest') diff --git a/tests/plugin/meson.build b/tests/plugin/meson.build index 2bbfc4b19e1e..322cafcdf6be 100644 --- a/tests/plugin/meson.build +++ b/tests/plugin/meson.build @@ -1,7 +1,13 @@ t = [] -foreach i : ['bb', 'empty', 'insn', 'mem', 'syscall'] - t += shared_module(i, files(i + '.c'), - include_directories: '../../include/qemu', - dependencies: glib) -endforeach -alias_target('test-plugins', t) +if get_option('plugins') + foreach i : ['bb', 'empty', 'insn', 'mem', 'syscall'] + t += shared_module(i, files(i + '.c'), + include_directories: '../../include/qemu', + dependencies: glib) + endforeach +endif +if t.length() > 0 + alias_target('test-plugins', t) +else + run_target('test-plugins', command: find_program('true')) +endif From b86dc5cb0b4105fa8ad29e822ab5d21c589c5ec5 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 13 Sep 2023 21:44:08 +0100 Subject: [PATCH 113/208] esp: use correct type for esp_dma_enable() in sysbus_esp_gpio_demux() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The call to esp_dma_enable() was being made with the SYSBUS_ESP type instead of the ESP type. This meant that when GPIO 1 was being used to trigger a DMA request from an external DMA controller, the setting of ESPState's dma_enabled field would clobber unknown memory whilst the dma_cb callback pointer would typically return NULL so the DMA request would never start. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Message-ID: <20230913204410.65650-2-mark.cave-ayland@ilande.co.uk> Signed-off-by: Paolo Bonzini --- hw/scsi/esp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index e52188d0228d..4218a6a96054 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -1395,7 +1395,7 @@ static void sysbus_esp_gpio_demux(void *opaque, int irq, int level) parent_esp_reset(s, irq, level); break; case 1: - esp_dma_enable(opaque, irq, level); + esp_dma_enable(s, irq, level); break; } } From 77668e4b9bca03a856c27ba899a2513ddf52bb52 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 13 Sep 2023 21:44:09 +0100 Subject: [PATCH 114/208] esp: restrict non-DMA transfer length to that of available data In the case where a SCSI layer transfer is incorrectly terminated, it is possible for a TI command to cause a SCSI buffer overflow due to the expected transfer data length being less than the available data in the FIFO. When this occurs the unsigned async_len variable underflows and becomes a large offset which writes past the end of the allocated SCSI buffer. Restrict the non-DMA transfer length to be the smallest of the expected transfer length and the available FIFO data to ensure that it is no longer possible for the SCSI buffer overflow to occur. Signed-off-by: Mark Cave-Ayland Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1810 Reviewed-by: Thomas Huth Message-ID: <20230913204410.65650-3-mark.cave-ayland@ilande.co.uk> Signed-off-by: Paolo Bonzini --- hw/scsi/esp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 4218a6a96054..9b11d8c5738a 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -759,7 +759,8 @@ static void esp_do_nodma(ESPState *s) } if (to_device) { - len = MIN(fifo8_num_used(&s->fifo), ESP_FIFO_SZ); + len = MIN(s->async_len, ESP_FIFO_SZ); + len = MIN(len, fifo8_num_used(&s->fifo)); esp_fifo_pop_buf(&s->fifo, s->async_buf, len); s->async_buf += len; s->async_len -= len; From be2b619a17345d007bcf9987a3e4afd1edea3e4f Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 13 Sep 2023 21:44:10 +0100 Subject: [PATCH 115/208] scsi-disk: ensure that FORMAT UNIT commands are terminated Otherwise when a FORMAT UNIT command is issued, the SCSI layer can become confused because it can find itself in the situation where it thinks there is still data to be transferred which can cause the next emulated SCSI command to fail. Signed-off-by: Mark Cave-Ayland Fixes: 6ab71761 ("scsi-disk: add FORMAT UNIT command") Tested-by: Thomas Huth Message-ID: <20230913204410.65650-4-mark.cave-ayland@ilande.co.uk> Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-disk.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 477ee2bcd47a..6691f5edb841 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -1959,6 +1959,10 @@ static void scsi_disk_emulate_write_data(SCSIRequest *req) scsi_disk_emulate_write_same(r, r->iov.iov_base); break; + case FORMAT_UNIT: + scsi_req_complete(&r->req, GOOD); + break; + default: abort(); } From 0c1a5299ab1d04ade6e6ff0fa2bc98e33cecaa80 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 28 Sep 2023 09:49:15 +0200 Subject: [PATCH 116/208] crypto: only include tls-cipher-suites in emulators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tls-cipher-suites is an object that is used to inject TLS configuration into the guest (via fw_cfg). It is never used for host-side TLS operation, and therefore it need not be available in the tools. Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- crypto/meson.build | 3 ++- hw/nvram/meson.build | 6 +----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/crypto/meson.build b/crypto/meson.build index 9ac1a898027a..c46f9c22a7fe 100644 --- a/crypto/meson.build +++ b/crypto/meson.build @@ -46,7 +46,8 @@ endif if have_afalg crypto_ss.add(if_true: files('afalg.c', 'cipher-afalg.c', 'hash-afalg.c')) endif -crypto_ss.add(when: gnutls, if_true: files('tls-cipher-suites.c')) + +system_ss.add(when: gnutls, if_true: files('tls-cipher-suites.c')) util_ss.add(files( 'aes.c', diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index 988dff6f8e5d..75e415b1a01b 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -1,8 +1,4 @@ -if have_system or have_tools - # QOM interfaces must be available anytime QOM is used. - qom_ss.add(files('fw_cfg-interface.c')) -endif - +system_ss.add(files('fw_cfg-interface.c')) system_ss.add(files('fw_cfg.c')) system_ss.add(when: 'CONFIG_CHRP_NVRAM', if_true: files('chrp_nvram.c')) system_ss.add(when: 'CONFIG_DS1225Y', if_true: files('ds1225y.c')) From 9e58d7a7561ace2e4ed62049f9d0ff488e1bb7f1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 25 Sep 2023 13:08:27 +0200 Subject: [PATCH 117/208] ui/vnc: Require audiodev= to enable audio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If there is no audiodev do not send the audio ack in response to VNC_ENCODING_AUDIO, so that clients aren't told audio exists, and immediately drop the client if they try to send any audio control messages when audio is not advertised. Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- docs/about/deprecated.rst | 8 +++----- docs/about/removed-features.rst | 6 ++++++ ui/vnc.c | 11 ++++++++++- ui/vnc.h | 2 ++ 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 8f3fef97bd45..c07bf58dde18 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -45,13 +45,11 @@ backend settings instead of environment variables. To ease migration to the new format, the ``-audiodev-help`` option can be used to convert the current values of the environment variables to ``-audiodev`` options. -Creating sound card devices and vnc without ``audiodev=`` property (since 4.2) -'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +Creating sound card devices without ``audiodev=`` property (since 4.2) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' When not using the deprecated legacy audio config, each sound card -should specify an ``audiodev=`` property. Additionally, when using -vnc, you should specify an ``audiodev=`` property if you plan to -transmit audio through the VNC protocol. +should specify an ``audiodev=`` property. Short-form boolean options (since 6.0) '''''''''''''''''''''''''''''''''''''' diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index 97ec47f1d251..276060b320c0 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -436,6 +436,12 @@ the process listing. This was replaced by the new ``password-secret`` option which lets the password be securely provided on the command line using a ``secret`` object instance. +Creating vnc without ``audiodev=`` property (removed in 8.2) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +When using vnc, you should specify an ``audiodev=`` property if +you plan to transmit audio through the VNC protocol. + QEMU Machine Protocol (QMP) commands ------------------------------------ diff --git a/ui/vnc.c b/ui/vnc.c index c302bb07a5bc..acb56461b2d4 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -2195,7 +2195,10 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) send_ext_key_event_ack(vs); break; case VNC_ENCODING_AUDIO: - send_ext_audio_ack(vs); + if (vs->vd->audio_state) { + vs->features |= VNC_FEATURE_AUDIO_MASK; + send_ext_audio_ack(vs); + } break; case VNC_ENCODING_WMVi: vs->features |= VNC_FEATURE_WMVI_MASK; @@ -2502,6 +2505,12 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) read_u32(data, 4), read_u32(data, 8)); break; case VNC_MSG_CLIENT_QEMU_AUDIO: + if (!vnc_has_feature(vs, VNC_FEATURE_AUDIO)) { + error_report("Audio message %d with audio disabled", read_u8(data, 2)); + vnc_client_error(vs); + break; + } + if (len == 2) return 4; diff --git a/ui/vnc.h b/ui/vnc.h index 757fa83044e7..96d19dce1998 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -464,6 +464,7 @@ enum VncFeatures { VNC_FEATURE_LED_STATE, VNC_FEATURE_XVP, VNC_FEATURE_CLIPBOARD_EXT, + VNC_FEATURE_AUDIO, }; #define VNC_FEATURE_RESIZE_MASK (1 << VNC_FEATURE_RESIZE) @@ -481,6 +482,7 @@ enum VncFeatures { #define VNC_FEATURE_LED_STATE_MASK (1 << VNC_FEATURE_LED_STATE) #define VNC_FEATURE_XVP_MASK (1 << VNC_FEATURE_XVP) #define VNC_FEATURE_CLIPBOARD_EXT_MASK (1 << VNC_FEATURE_CLIPBOARD_EXT) +#define VNC_FEATURE_AUDIO_MASK (1 << VNC_FEATURE_AUDIO) /* Client -> Server message IDs */ From aaa6a6f93dc88f9201b9872fa64a565d52628208 Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Mon, 25 Apr 2022 10:21:57 +0200 Subject: [PATCH 118/208] audio: Require AudioState in AUD_add_capture Since all callers require a valid audiodev this function can now safely abort in case of missing AudioState. Signed-off-by: Martin Kletzander Message-ID: Signed-off-by: Paolo Bonzini --- audio/audio.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 2f4796571179..d4387cb3e21f 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1876,10 +1876,8 @@ CaptureVoiceOut *AUD_add_capture( struct capture_callback *cb; if (!s) { - if (!legacy_config) { - dolog("Capturing without setting an audiodev is deprecated\n"); - } - s = audio_init(NULL, NULL); + error_report("Capturing without setting an audiodev is not supported"); + abort(); } if (!audio_get_pdo_out(s->dev)->mixing_engine) { From f6061733a96314ccb732efe6c91357d66f8970af Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 22 Sep 2023 19:13:44 +0200 Subject: [PATCH 119/208] audio: allow returning an error from the driver init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An error is already printed by audio_driver_init, but we can make it more precise if the driver can return an Error *. Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- audio/alsaaudio.c | 2 +- audio/audio.c | 13 ++++++++++--- audio/audio_int.h | 2 +- audio/coreaudio.m | 2 +- audio/dbusaudio.c | 2 +- audio/dsoundaudio.c | 2 +- audio/jackaudio.c | 2 +- audio/noaudio.c | 2 +- audio/ossaudio.c | 11 ++++++++--- audio/paaudio.c | 7 +++++-- audio/pwaudio.c | 16 +++++++++------- audio/sdlaudio.c | 5 +++-- audio/sndioaudio.c | 2 +- audio/spiceaudio.c | 5 ++++- audio/wavaudio.c | 2 +- 15 files changed, 48 insertions(+), 27 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 057571dd1e03..6fb78e5b9729 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -904,7 +904,7 @@ static void alsa_init_per_direction(AudiodevAlsaPerDirectionOptions *apdo) } } -static void *alsa_audio_init(Audiodev *dev) +static void *alsa_audio_init(Audiodev *dev, Error **errp) { AudiodevAlsaOptions *aopts; assert(dev->driver == AUDIODEV_DRIVER_ALSA); diff --git a/audio/audio.c b/audio/audio.c index d4387cb3e21f..fdc34a77520f 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -33,6 +33,7 @@ #include "qapi/qapi-visit-audio.h" #include "qapi/qapi-commands-audio.h" #include "qemu/cutils.h" +#include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/module.h" #include "qemu/help_option.h" @@ -1555,7 +1556,9 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size) static int audio_driver_init(AudioState *s, struct audio_driver *drv, bool msg, Audiodev *dev) { - s->drv_opaque = drv->init(dev); + Error *local_err = NULL; + + s->drv_opaque = drv->init(dev, &local_err); if (s->drv_opaque) { if (!drv->pcm_ops->get_buffer_in) { @@ -1572,8 +1575,12 @@ static int audio_driver_init(AudioState *s, struct audio_driver *drv, s->drv = drv; return 0; } else { - if (msg) { - dolog("Could not init `%s' audio driver\n", drv->name); + if (!msg) { + error_free(local_err); + } else if (local_err) { + error_report_err(local_err); + } else { + error_report("Could not init `%s' audio driver", drv->name); } return -1; } diff --git a/audio/audio_int.h b/audio/audio_int.h index e57ff50155a5..06e815de9f6c 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -140,7 +140,7 @@ typedef struct audio_driver audio_driver; struct audio_driver { const char *name; const char *descr; - void *(*init) (Audiodev *); + void *(*init) (Audiodev *, Error **); void (*fini) (void *); #ifdef CONFIG_GIO void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager, bool p2p); diff --git a/audio/coreaudio.m b/audio/coreaudio.m index 4695291621a3..7cfb38fb6ae3 100644 --- a/audio/coreaudio.m +++ b/audio/coreaudio.m @@ -644,7 +644,7 @@ static void coreaudio_enable_out(HWVoiceOut *hw, bool enable) update_device_playback_state(core); } -static void *coreaudio_audio_init(Audiodev *dev) +static void *coreaudio_audio_init(Audiodev *dev, Error **errp) { return dev; } diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index 7a11fbfb4209..310ca997ff41 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -395,7 +395,7 @@ dbus_enable_in(HWVoiceIn *hw, bool enable) } static void * -dbus_audio_init(Audiodev *dev) +dbus_audio_init(Audiodev *dev, Error **errp) { DBusAudio *da = g_new0(DBusAudio, 1); diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index 3fb67ec3eed4..eefde88edcb1 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -619,7 +619,7 @@ static void dsound_audio_fini (void *opaque) g_free(s); } -static void *dsound_audio_init(Audiodev *dev) +static void *dsound_audio_init(Audiodev *dev, Error **errp) { int err; HRESULT hr; diff --git a/audio/jackaudio.c b/audio/jackaudio.c index e1eaa3477dc6..823e7d96baee 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -645,7 +645,7 @@ static int qjack_thread_creator(jack_native_thread_t *thread, } #endif -static void *qjack_init(Audiodev *dev) +static void *qjack_init(Audiodev *dev, Error **errp) { assert(dev->driver == AUDIODEV_DRIVER_JACK); return dev; diff --git a/audio/noaudio.c b/audio/noaudio.c index 4fdee5adecff..a36bfeffd14b 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -104,7 +104,7 @@ static void no_enable_in(HWVoiceIn *hw, bool enable) } } -static void *no_audio_init(Audiodev *dev) +static void *no_audio_init(Audiodev *dev, Error **errp) { return &no_audio_init; } diff --git a/audio/ossaudio.c b/audio/ossaudio.c index e8d732b612c6..ec4448d573dd 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -28,6 +28,7 @@ #include "qemu/main-loop.h" #include "qemu/module.h" #include "qemu/host-utils.h" +#include "qapi/error.h" #include "audio.h" #include "trace.h" @@ -736,7 +737,7 @@ static void oss_init_per_direction(AudiodevOssPerDirectionOptions *opdo) } } -static void *oss_audio_init(Audiodev *dev) +static void *oss_audio_init(Audiodev *dev, Error **errp) { AudiodevOssOptions *oopts; assert(dev->driver == AUDIODEV_DRIVER_OSS); @@ -745,8 +746,12 @@ static void *oss_audio_init(Audiodev *dev) oss_init_per_direction(oopts->in); oss_init_per_direction(oopts->out); - if (access(oopts->in->dev ?: "/dev/dsp", R_OK | W_OK) < 0 || - access(oopts->out->dev ?: "/dev/dsp", R_OK | W_OK) < 0) { + if (access(oopts->in->dev ?: "/dev/dsp", R_OK | W_OK) < 0) { + error_setg_errno(errp, errno, "%s not accessible", oopts->in->dev ?: "/dev/dsp"); + return NULL; + } + if (access(oopts->out->dev ?: "/dev/dsp", R_OK | W_OK) < 0) { + error_setg_errno(errp, errno, "%s not accessible", oopts->out->dev ?: "/dev/dsp"); return NULL; } return dev; diff --git a/audio/paaudio.c b/audio/paaudio.c index 529b39daacc7..39bd6cfa38a5 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -3,7 +3,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" #include "audio.h" -#include "qapi/opts-visitor.h" +#include "qapi/error.h" #include @@ -818,7 +818,7 @@ static void *qpa_conn_init(const char *server) return NULL; } -static void *qpa_audio_init(Audiodev *dev) +static void *qpa_audio_init(Audiodev *dev, Error **errp) { paaudio *g; AudiodevPaOptions *popts = &dev->u.pa; @@ -834,10 +834,12 @@ static void *qpa_audio_init(Audiodev *dev) runtime = getenv("XDG_RUNTIME_DIR"); if (!runtime) { + error_setg(errp, "XDG_RUNTIME_DIR not set"); return NULL; } snprintf(pidfile, sizeof(pidfile), "%s/pulse/pid", runtime); if (stat(pidfile, &st) != 0) { + error_setg_errno(errp, errno, "could not stat pidfile %s", pidfile); return NULL; } } @@ -867,6 +869,7 @@ static void *qpa_audio_init(Audiodev *dev) } if (!g->conn) { g_free(g); + error_setg(errp, "could not connect to PulseAudio server"); return NULL; } diff --git a/audio/pwaudio.c b/audio/pwaudio.c index b6a38738ee93..1020cb11df1b 100644 --- a/audio/pwaudio.c +++ b/audio/pwaudio.c @@ -13,6 +13,7 @@ #include "audio.h" #include #include "qemu/error-report.h" +#include "qapi/error.h" #include #include #include @@ -736,7 +737,7 @@ static const struct pw_core_events core_events = { }; static void * -qpw_audio_init(Audiodev *dev) +qpw_audio_init(Audiodev *dev, Error **errp) { g_autofree pwaudio *pw = g_new0(pwaudio, 1); @@ -748,19 +749,19 @@ qpw_audio_init(Audiodev *dev) pw->dev = dev; pw->thread_loop = pw_thread_loop_new("PipeWire thread loop", NULL); if (pw->thread_loop == NULL) { - error_report("Could not create PipeWire loop: %s", g_strerror(errno)); + error_setg_errno(errp, errno, "Could not create PipeWire loop"); goto fail; } pw->context = pw_context_new(pw_thread_loop_get_loop(pw->thread_loop), NULL, 0); if (pw->context == NULL) { - error_report("Could not create PipeWire context: %s", g_strerror(errno)); + error_setg_errno(errp, errno, "Could not create PipeWire context"); goto fail; } if (pw_thread_loop_start(pw->thread_loop) < 0) { - error_report("Could not start PipeWire loop: %s", g_strerror(errno)); + error_setg_errno(errp, errno, "Could not start PipeWire loop"); goto fail; } @@ -769,13 +770,13 @@ qpw_audio_init(Audiodev *dev) pw->core = pw_context_connect(pw->context, NULL, 0); if (pw->core == NULL) { pw_thread_loop_unlock(pw->thread_loop); - goto fail; + goto fail_error; } if (pw_core_add_listener(pw->core, &pw->core_listener, &core_events, pw) < 0) { pw_thread_loop_unlock(pw->thread_loop); - goto fail; + goto fail_error; } if (wait_resync(pw) < 0) { pw_thread_loop_unlock(pw->thread_loop); @@ -785,8 +786,9 @@ qpw_audio_init(Audiodev *dev) return g_steal_pointer(&pw); +fail_error: + error_setg(errp, "Failed to initialize PW context"); fail: - AUD_log(AUDIO_CAP, "Failed to initialize PW context"); if (pw->thread_loop) { pw_thread_loop_stop(pw->thread_loop); } diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index 68a237b76b45..4d8473d9ece8 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -26,6 +26,7 @@ #include #include #include "qemu/module.h" +#include "qapi/error.h" #include "audio.h" #ifndef _WIN32 @@ -449,10 +450,10 @@ static void sdl_enable_in(HWVoiceIn *hw, bool enable) SDL_PauseAudioDevice(sdl->devid, !enable); } -static void *sdl_audio_init(Audiodev *dev) +static void *sdl_audio_init(Audiodev *dev, Error **errp) { if (SDL_InitSubSystem (SDL_INIT_AUDIO)) { - sdl_logerr ("SDL failed to initialize audio subsystem\n"); + error_setg(errp, "SDL failed to initialize audio subsystem"); return NULL; } diff --git a/audio/sndioaudio.c b/audio/sndioaudio.c index 3fde01fdbd59..1e35925a497e 100644 --- a/audio/sndioaudio.c +++ b/audio/sndioaudio.c @@ -518,7 +518,7 @@ static void sndio_fini_in(HWVoiceIn *hw) sndio_fini(self); } -static void *sndio_audio_init(Audiodev *dev) +static void *sndio_audio_init(Audiodev *dev, Error **errp) { assert(dev->driver == AUDIODEV_DRIVER_SNDIO); return dev; diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index d17ef1a25efb..7f02f7285cf2 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -22,6 +22,7 @@ #include "qemu/module.h" #include "qemu/error-report.h" #include "qemu/timer.h" +#include "qapi/error.h" #include "ui/qemu-spice.h" #define AUDIO_CAP "spice" @@ -71,11 +72,13 @@ static const SpiceRecordInterface record_sif = { .base.minor_version = SPICE_INTERFACE_RECORD_MINOR, }; -static void *spice_audio_init(Audiodev *dev) +static void *spice_audio_init(Audiodev *dev, Error **errp) { if (!using_spice) { + error_setg(errp, "Cannot use spice audio without -spice"); return NULL; } + return &spice_audio_init; } diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 6445a2cb90c5..26b03906d592 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -182,7 +182,7 @@ static void wav_enable_out(HWVoiceOut *hw, bool enable) } } -static void *wav_audio_init(Audiodev *dev) +static void *wav_audio_init(Audiodev *dev, Error **errp) { assert(dev->driver == AUDIODEV_DRIVER_WAV); return dev; From 176adafca72ecc35e7f1f011deb52ca1ae091df6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 22 Sep 2023 17:29:19 +0200 Subject: [PATCH 120/208] audio: return Error ** from audio_state_by_name Remove duplicate error formatting code. Signed-off-by: Paolo Bonzini --- audio/audio-hmp-cmds.c | 6 ++++-- audio/audio.c | 3 ++- audio/audio.h | 2 +- hw/core/qdev-properties-system.c | 16 ++++------------ ui/dbus.c | 3 +-- ui/vnc.c | 3 +-- 6 files changed, 13 insertions(+), 20 deletions(-) diff --git a/audio/audio-hmp-cmds.c b/audio/audio-hmp-cmds.c index 1237ce9e7509..c9608b715b8d 100644 --- a/audio/audio-hmp-cmds.c +++ b/audio/audio-hmp-cmds.c @@ -26,6 +26,7 @@ #include "audio/audio.h" #include "monitor/hmp.h" #include "monitor/monitor.h" +#include "qapi/error.h" #include "qapi/qmp/qdict.h" static QLIST_HEAD (capture_list_head, CaptureState) capture_head; @@ -65,10 +66,11 @@ void hmp_wavcapture(Monitor *mon, const QDict *qdict) int nchannels = qdict_get_try_int(qdict, "nchannels", 2); const char *audiodev = qdict_get_str(qdict, "audiodev"); CaptureState *s; - AudioState *as = audio_state_by_name(audiodev); + Error *local_err = NULL; + AudioState *as = audio_state_by_name(audiodev, &local_err); if (!as) { - monitor_printf(mon, "Audiodev '%s' not found\n", audiodev); + error_report_err(local_err); return; } diff --git a/audio/audio.c b/audio/audio.c index fdc34a77520f..874a4c3c412c 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -2260,7 +2260,7 @@ int audio_buffer_bytes(AudiodevPerDirectionOptions *pdo, audioformat_bytes_per_sample(as->fmt); } -AudioState *audio_state_by_name(const char *name) +AudioState *audio_state_by_name(const char *name, Error **errp) { AudioState *s; QTAILQ_FOREACH(s, &audio_states, list) { @@ -2269,6 +2269,7 @@ AudioState *audio_state_by_name(const char *name) return s; } } + error_setg(errp, "audiodev '%s' not found", name); return NULL; } diff --git a/audio/audio.h b/audio/audio.h index 01bdc567fb17..e0c13b5dcdf6 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -174,7 +174,7 @@ bool audio_init_audiodevs(void); void audio_help(void); void audio_legacy_help(void); -AudioState *audio_state_by_name(const char *name); +AudioState *audio_state_by_name(const char *name, Error **errp); const char *audio_get_id(QEMUSoundCard *card); #define DEFINE_AUDIO_PROPERTIES(_s, _f) \ diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 41b7e682c781..688340610ec1 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -480,24 +480,16 @@ static void set_audiodev(Object *obj, Visitor *v, const char* name, Property *prop = opaque; QEMUSoundCard *card = object_field_prop_ptr(obj, prop); AudioState *state; - int err = 0; - char *str; + g_autofree char *str = NULL; if (!visit_type_str(v, name, &str, errp)) { return; } - state = audio_state_by_name(str); - - if (!state) { - err = -ENOENT; - goto out; + state = audio_state_by_name(str, errp); + if (state) { + card->state = state; } - card->state = state; - -out: - error_set_from_qdev_prop_error(errp, err, obj, name, str); - g_free(str); } const PropertyInfo qdev_prop_audiodev = { diff --git a/ui/dbus.c b/ui/dbus.c index 32f1bbe81ae1..866467ad2e33 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -220,9 +220,8 @@ dbus_display_complete(UserCreatable *uc, Error **errp) } if (dd->audiodev && *dd->audiodev) { - AudioState *audio_state = audio_state_by_name(dd->audiodev); + AudioState *audio_state = audio_state_by_name(dd->audiodev, errp); if (!audio_state) { - error_setg(errp, "Audiodev '%s' not found", dd->audiodev); return; } if (!g_str_equal(audio_state->drv->name, "dbus")) { diff --git a/ui/vnc.c b/ui/vnc.c index acb56461b2d4..829294691302 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -4181,9 +4181,8 @@ void vnc_display_open(const char *id, Error **errp) audiodev = qemu_opt_get(opts, "audiodev"); if (audiodev) { - vd->audio_state = audio_state_by_name(audiodev); + vd->audio_state = audio_state_by_name(audiodev, errp); if (!vd->audio_state) { - error_setg(errp, "Audiodev '%s' not found", audiodev); goto fail; } } From 5c63d141dc8768c7418893beef8f151a13883e65 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 22 Sep 2023 18:36:28 +0200 Subject: [PATCH 121/208] audio: commonize voice initialization Move some mostly irrelevant code out of audio_init. Signed-off-by: Paolo Bonzini --- audio/audio.c | 19 ++----------------- audio/audio_template.h | 9 ++++++++- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 874a4c3c412c..bb1734a95d3b 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1570,8 +1570,8 @@ static int audio_driver_init(AudioState *s, struct audio_driver *drv, drv->pcm_ops->put_buffer_out = audio_generic_put_buffer_out; } - audio_init_nb_voices_out(s, drv); - audio_init_nb_voices_in(s, drv); + audio_init_nb_voices_out(s, drv, 1); + audio_init_nb_voices_in(s, drv, 0); s->drv = drv; return 0; } else { @@ -1774,21 +1774,6 @@ static AudioState *audio_init(Audiodev *dev, const char *name) s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s); - s->nb_hw_voices_out = audio_get_pdo_out(dev)->voices; - s->nb_hw_voices_in = audio_get_pdo_in(dev)->voices; - - if (s->nb_hw_voices_out < 1) { - dolog ("Bogus number of playback voices %d, setting to 1\n", - s->nb_hw_voices_out); - s->nb_hw_voices_out = 1; - } - - if (s->nb_hw_voices_in < 0) { - dolog ("Bogus number of capture voices %d, setting to 0\n", - s->nb_hw_voices_in); - s->nb_hw_voices_in = 0; - } - if (drvname) { driver = audio_driver_lookup(drvname); if (driver) { diff --git a/audio/audio_template.h b/audio/audio_template.h index dc0c74aa7464..7ccfec01168c 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -37,11 +37,12 @@ #endif static void glue(audio_init_nb_voices_, TYPE)(AudioState *s, - struct audio_driver *drv) + struct audio_driver *drv, int min_voices) { int max_voices = glue (drv->max_voices_, TYPE); size_t voice_size = glue(drv->voice_size_, TYPE); + glue (s->nb_hw_voices_, TYPE) = glue(audio_get_pdo_, TYPE)(s->dev)->voices; if (glue (s->nb_hw_voices_, TYPE) > max_voices) { if (!max_voices) { #ifdef DAC @@ -56,6 +57,12 @@ static void glue(audio_init_nb_voices_, TYPE)(AudioState *s, glue (s->nb_hw_voices_, TYPE) = max_voices; } + if (glue (s->nb_hw_voices_, TYPE) < min_voices) { + dolog ("Bogus number of " NAME " voices %d, setting to %d\n", + glue (s->nb_hw_voices_, TYPE), + min_voices); + } + if (audio_bug(__func__, !voice_size && max_voices)) { dolog ("drv=`%s' voice_size=0 max_voices=%d\n", drv->name, max_voices); From e3299631720732ceb02cf3f10b175c5e6ffcad39 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 22 Sep 2023 17:46:28 +0200 Subject: [PATCH 122/208] audio: simplify flow in audio_init Merge two ifs into one. Signed-off-by: Paolo Bonzini --- audio/audio.c | 64 +++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index bb1734a95d3b..2e22664daf9d 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1707,12 +1707,12 @@ static AudiodevListEntry *audiodev_find( * if dev == NULL => legacy implicit initialization, return the already created * state or create a new one */ -static AudioState *audio_init(Audiodev *dev, const char *name) +static AudioState *audio_init(Audiodev *dev) { static bool atexit_registered; size_t i; int done = 0; - const char *drvname = NULL; + const char *drvname; VMChangeStateEntry *vmse; AudioState *s; struct audio_driver *driver; @@ -1736,33 +1736,7 @@ static AudioState *audio_init(Audiodev *dev, const char *name) } } - if (dev) { - /* -audiodev option */ - legacy_config = false; - drvname = AudiodevDriver_str(dev->driver); - } else if (!QTAILQ_EMPTY(&audio_states)) { - if (!legacy_config) { - dolog("Device %s: audiodev default parameter is deprecated, please " - "specify audiodev=%s\n", name, - QTAILQ_FIRST(&audio_states)->dev->id); - } - return QTAILQ_FIRST(&audio_states); - } else { - /* legacy implicit initialization */ - head = audio_handle_legacy_opts(); - /* - * In case of legacy initialization, all Audiodevs in the list will have - * the same configuration (except the driver), so it doesn't matter which - * one we chose. We need an Audiodev to set up AudioState before we can - * init a driver. Also note that dev at this point is still in the - * list. - */ - dev = QSIMPLEQ_FIRST(&head)->dev; - audio_validate_opts(dev, &error_abort); - } - s = g_new0(AudioState, 1); - s->dev = dev; QLIST_INIT (&s->hw_head_out); QLIST_INIT (&s->hw_head_in); @@ -1774,7 +1748,10 @@ static AudioState *audio_init(Audiodev *dev, const char *name) s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s); - if (drvname) { + if (dev) { + /* -audiodev option */ + s->dev = dev; + drvname = AudiodevDriver_str(dev->driver); driver = audio_driver_lookup(drvname); if (driver) { done = !audio_driver_init(s, driver, true, dev); @@ -1786,6 +1763,18 @@ static AudioState *audio_init(Audiodev *dev, const char *name) return NULL; } } else { + /* legacy implicit initialization */ + head = audio_handle_legacy_opts(); + /* + * In case of legacy initialization, all Audiodevs in the list will have + * the same configuration (except the driver), so it doesn't matter which + * one we chose. We need an Audiodev to set up AudioState before we can + * init a driver. Also note that dev at this point is still in the + * list. + */ + dev = QSIMPLEQ_FIRST(&head)->dev; + audio_validate_opts(dev, &error_abort); + for (i = 0; audio_prio_list[i]; i++) { AudiodevListEntry *e = audiodev_find(&head, audio_prio_list[i]); driver = audio_driver_lookup(audio_prio_list[i]); @@ -1800,8 +1789,9 @@ static AudioState *audio_init(Audiodev *dev, const char *name) } } } + + audio_free_audiodev_list(&head); } - audio_free_audiodev_list(&head); if (!done) { driver = audio_driver_lookup("none"); @@ -1841,7 +1831,16 @@ void audio_free_audiodev_list(AudiodevListHead *head) void AUD_register_card (const char *name, QEMUSoundCard *card) { if (!card->state) { - card->state = audio_init(NULL, name); + if (!QTAILQ_EMPTY(&audio_states)) { + if (!legacy_config) { + dolog("Device %s: audiodev default parameter is deprecated, please " + "specify audiodev=%s\n", name, + QTAILQ_FIRST(&audio_states)->dev->id); + } + card->state = QTAILQ_FIRST(&audio_states); + } else { + card->state = audio_init(NULL); + } } card->name = g_strdup (name); @@ -2171,6 +2170,7 @@ void audio_define(Audiodev *dev) e = g_new0(AudiodevListEntry, 1); e->dev = dev; QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next); + legacy_config = false; } bool audio_init_audiodevs(void) @@ -2178,7 +2178,7 @@ bool audio_init_audiodevs(void) AudiodevListEntry *e; QSIMPLEQ_FOREACH(e, &audiodevs, next) { - if (!audio_init(e->dev, NULL)) { + if (!audio_init(e->dev)) { return false; } } From 69a802792ab3705074585a75f5645297ae9f6794 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 5 Sep 2023 11:41:05 +0200 Subject: [PATCH 123/208] audio: remove QEMU_AUDIO_* and -audio-help support These have been deprecated for a long time, and the introduction of -audio in 7.1.0 has cemented the new way of specifying an audio backend's parameters. However, there is still a need for simple configuration of the audio backend in the desktop case; therefore, if no audiodev is passed to audio_init(), go through a bunch of simple Audiodev* structures and pick the first that can be initialized successfully. The only QEMU_AUDIO_* option that is left in, waiting for a better idea, is QEMU_AUDIO_DRV=none which is used by qtest. Remove all the parsing code, including the concept of "can_be_default" audio drivers: now that audio_prio_list[] is only used in a single place, wav can be excluded directly in that function. Signed-off-by: Paolo Bonzini --- audio/alsaaudio.c | 1 - audio/audio.c | 138 ++++---- audio/audio.h | 1 - audio/audio_int.h | 5 - audio/audio_legacy.c | 591 -------------------------------- audio/coreaudio.m | 1 - audio/dbusaudio.c | 1 - audio/dsoundaudio.c | 1 - audio/jackaudio.c | 1 - audio/meson.build | 1 - audio/noaudio.c | 1 - audio/ossaudio.c | 1 - audio/paaudio.c | 1 - audio/pwaudio.c | 1 - audio/sdlaudio.c | 1 - audio/sndioaudio.c | 1 - audio/wavaudio.c | 1 - docs/about/deprecated.rst | 8 - docs/about/removed-features.rst | 6 + qemu-options.hx | 10 - softmmu/vl.c | 4 - 21 files changed, 65 insertions(+), 711 deletions(-) delete mode 100644 audio/audio_legacy.c diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 6fb78e5b9729..cacae1ea59ce 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -960,7 +960,6 @@ static struct audio_driver alsa_audio_driver = { .init = alsa_audio_init, .fini = alsa_audio_fini, .pcm_ops = &alsa_pcm_ops, - .can_be_default = 1, .max_voices_out = INT_MAX, .max_voices_in = INT_MAX, .voice_size_out = sizeof (ALSAVoiceOut), diff --git a/audio/audio.c b/audio/audio.c index 2e22664daf9d..818d79e50f0a 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -32,6 +32,7 @@ #include "qapi/qobject-input-visitor.h" #include "qapi/qapi-visit-audio.h" #include "qapi/qapi-commands-audio.h" +#include "qapi/qmp/qdict.h" #include "qemu/cutils.h" #include "qemu/error-report.h" #include "qemu/log.h" @@ -62,19 +63,22 @@ const char *audio_prio_list[] = { "spice", CONFIG_AUDIO_DRIVERS "none", - "wav", NULL }; static QLIST_HEAD(, audio_driver) audio_drivers; -static AudiodevListHead audiodevs = QSIMPLEQ_HEAD_INITIALIZER(audiodevs); +static AudiodevListHead audiodevs = + QSIMPLEQ_HEAD_INITIALIZER(audiodevs); +static AudiodevListHead default_audiodevs = + QSIMPLEQ_HEAD_INITIALIZER(default_audiodevs); + void audio_driver_register(audio_driver *drv) { QLIST_INSERT_HEAD(&audio_drivers, drv, next); } -audio_driver *audio_driver_lookup(const char *name) +static audio_driver *audio_driver_lookup(const char *name) { struct audio_driver *d; Error *local_err = NULL; @@ -112,8 +116,6 @@ const struct mixeng_volume nominal_volume = { #endif }; -static bool legacy_config = true; - int audio_bug (const char *funcname, int cond) { if (cond) { @@ -1688,17 +1690,41 @@ static const VMStateDescription vmstate_audio = { static void audio_validate_opts(Audiodev *dev, Error **errp); -static AudiodevListEntry *audiodev_find( - AudiodevListHead *head, const char *drvname) +static void audio_create_default_audiodevs(void) { - AudiodevListEntry *e; - QSIMPLEQ_FOREACH(e, head, next) { - if (strcmp(AudiodevDriver_str(e->dev->driver), drvname) == 0) { - return e; - } + const char *drvname = getenv("QEMU_AUDIO_DRV"); + + /* QEMU_AUDIO_DRV=none is used by libqtest. */ + if (drvname && !g_str_equal(drvname, "none")) { + error_report("Please use -audiodev instead of QEMU_AUDIO_*"); + exit(1); } - return NULL; + for (int i = 0; audio_prio_list[i]; i++) { + if (drvname && !g_str_equal(drvname, audio_prio_list[i])) { + continue; + } + + if (audio_driver_lookup(audio_prio_list[i])) { + QDict *dict = qdict_new(); + Audiodev *dev = NULL; + AudiodevListEntry *e; + Visitor *v; + + qdict_put_str(dict, "driver", audio_prio_list[i]); + qdict_put_str(dict, "id", "#default"); + + v = qobject_input_visitor_new_keyval(QOBJECT(dict)); + qobject_unref(dict); + visit_type_Audiodev(v, NULL, &dev, &error_fatal); + visit_free(v); + + audio_validate_opts(dev, &error_abort); + e = g_new0(AudiodevListEntry, 1); + e->dev = dev; + QSIMPLEQ_INSERT_TAIL(&default_audiodevs, e, next); + } + } } /* @@ -1710,31 +1736,11 @@ static AudiodevListEntry *audiodev_find( static AudioState *audio_init(Audiodev *dev) { static bool atexit_registered; - size_t i; int done = 0; const char *drvname; VMChangeStateEntry *vmse; AudioState *s; struct audio_driver *driver; - /* silence gcc warning about uninitialized variable */ - AudiodevListHead head = QSIMPLEQ_HEAD_INITIALIZER(head); - - if (using_spice) { - /* - * When using spice allow the spice audio driver being picked - * as default. - * - * Temporary hack. Using audio devices without explicit - * audiodev= property is already deprecated. Same goes for - * the -soundhw switch. Once this support gets finally - * removed we can also drop the concept of a default audio - * backend and this can go away. - */ - driver = audio_driver_lookup("spice"); - if (driver) { - driver->can_be_default = 1; - } - } s = g_new0(AudioState, 1); @@ -1759,45 +1765,23 @@ static AudioState *audio_init(Audiodev *dev) dolog ("Unknown audio driver `%s'\n", drvname); } if (!done) { - free_audio_state(s); - return NULL; + goto out; } } else { - /* legacy implicit initialization */ - head = audio_handle_legacy_opts(); - /* - * In case of legacy initialization, all Audiodevs in the list will have - * the same configuration (except the driver), so it doesn't matter which - * one we chose. We need an Audiodev to set up AudioState before we can - * init a driver. Also note that dev at this point is still in the - * list. - */ - dev = QSIMPLEQ_FIRST(&head)->dev; - audio_validate_opts(dev, &error_abort); - - for (i = 0; audio_prio_list[i]; i++) { - AudiodevListEntry *e = audiodev_find(&head, audio_prio_list[i]); - driver = audio_driver_lookup(audio_prio_list[i]); - - if (e && driver) { - s->dev = dev = e->dev; - audio_validate_opts(dev, &error_abort); - done = !audio_driver_init(s, driver, false, dev); - if (done) { - e->dev = NULL; - break; - } + for (;;) { + AudiodevListEntry *e = QSIMPLEQ_FIRST(&default_audiodevs); + if (!e) { + dolog("no default audio driver available\n"); + goto out; } + s->dev = dev = e->dev; + drvname = AudiodevDriver_str(dev->driver); + driver = audio_driver_lookup(drvname); + if (!audio_driver_init(s, driver, false, dev)) { + break; + } + QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next); } - - audio_free_audiodev_list(&head); - } - - if (!done) { - driver = audio_driver_lookup("none"); - done = !audio_driver_init(s, driver, false, dev); - assert(done); - dolog("warning: Using timer based audio emulation\n"); } if (dev->timer_period <= 0) { @@ -1816,29 +1800,26 @@ static AudioState *audio_init(Audiodev *dev) QLIST_INIT (&s->card_head); vmstate_register (NULL, 0, &vmstate_audio, s); return s; -} -void audio_free_audiodev_list(AudiodevListHead *head) -{ - AudiodevListEntry *e; - while ((e = QSIMPLEQ_FIRST(head))) { - QSIMPLEQ_REMOVE_HEAD(head, next); - qapi_free_Audiodev(e->dev); - g_free(e); - } +out: + free_audio_state(s); + return NULL; } void AUD_register_card (const char *name, QEMUSoundCard *card) { if (!card->state) { if (!QTAILQ_EMPTY(&audio_states)) { - if (!legacy_config) { + if (QSIMPLEQ_EMPTY(&default_audiodevs)) { dolog("Device %s: audiodev default parameter is deprecated, please " "specify audiodev=%s\n", name, QTAILQ_FIRST(&audio_states)->dev->id); } card->state = QTAILQ_FIRST(&audio_states); } else { + if (QSIMPLEQ_EMPTY(&default_audiodevs)) { + audio_create_default_audiodevs(); + } card->state = audio_init(NULL); } } @@ -2170,7 +2151,6 @@ void audio_define(Audiodev *dev) e = g_new0(AudiodevListEntry, 1); e->dev = dev; QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next); - legacy_config = false; } bool audio_init_audiodevs(void) diff --git a/audio/audio.h b/audio/audio.h index e0c13b5dcdf6..34df8962a669 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -172,7 +172,6 @@ void audio_define(Audiodev *audio); void audio_parse_option(const char *opt); bool audio_init_audiodevs(void); void audio_help(void); -void audio_legacy_help(void); AudioState *audio_state_by_name(const char *name, Error **errp); const char *audio_get_id(QEMUSoundCard *card); diff --git a/audio/audio_int.h b/audio/audio_int.h index 06e815de9f6c..2d079d00a259 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -146,7 +146,6 @@ struct audio_driver { void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager, bool p2p); #endif struct audio_pcm_ops *pcm_ops; - int can_be_default; int max_voices_out; int max_voices_in; size_t voice_size_out; @@ -243,7 +242,6 @@ extern const struct mixeng_volume nominal_volume; extern const char *audio_prio_list[]; void audio_driver_register(audio_driver *drv); -audio_driver *audio_driver_lookup(const char *name); void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as); void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len); @@ -297,9 +295,6 @@ typedef struct AudiodevListEntry { } AudiodevListEntry; typedef QSIMPLEQ_HEAD(, AudiodevListEntry) AudiodevListHead; -AudiodevListHead audio_handle_legacy_opts(void); - -void audio_free_audiodev_list(AudiodevListHead *head); void audio_create_pdos(Audiodev *dev); AudiodevPerDirectionOptions *audio_get_pdo_in(Audiodev *dev); diff --git a/audio/audio_legacy.c b/audio/audio_legacy.c deleted file mode 100644 index dc72ba55e9af..000000000000 --- a/audio/audio_legacy.c +++ /dev/null @@ -1,591 +0,0 @@ -/* - * QEMU Audio subsystem: legacy configuration handling - * - * Copyright (c) 2015-2019 Zoltán Kővágó - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "qemu/osdep.h" -#include "audio.h" -#include "audio_int.h" -#include "qemu/cutils.h" -#include "qemu/timer.h" -#include "qapi/error.h" -#include "qapi/qapi-visit-audio.h" -#include "qapi/visitor-impl.h" - -#define AUDIO_CAP "audio-legacy" -#include "audio_int.h" - -static uint32_t toui32(const char *str) -{ - uint64_t ret; - if (parse_uint_full(str, 10, &ret) || ret > UINT32_MAX) { - dolog("Invalid integer value `%s'\n", str); - exit(1); - } - return ret; -} - -/* helper functions to convert env variables */ -static void get_bool(const char *env, bool *dst, bool *has_dst) -{ - const char *val = getenv(env); - if (val) { - *dst = toui32(val) != 0; - *has_dst = true; - } -} - -static void get_int(const char *env, uint32_t *dst, bool *has_dst) -{ - const char *val = getenv(env); - if (val) { - *dst = toui32(val); - *has_dst = true; - } -} - -static void get_str(const char *env, char **dst) -{ - const char *val = getenv(env); - if (val) { - g_free(*dst); - *dst = g_strdup(val); - } -} - -static void get_fmt(const char *env, AudioFormat *dst, bool *has_dst) -{ - const char *val = getenv(env); - if (val) { - size_t i; - for (i = 0; AudioFormat_lookup.size; ++i) { - if (strcasecmp(val, AudioFormat_lookup.array[i]) == 0) { - *dst = i; - *has_dst = true; - return; - } - } - - dolog("Invalid audio format `%s'\n", val); - exit(1); - } -} - - -#if defined(CONFIG_AUDIO_ALSA) || defined(CONFIG_AUDIO_DSOUND) -static void get_millis_to_usecs(const char *env, uint32_t *dst, bool *has_dst) -{ - const char *val = getenv(env); - if (val) { - *dst = toui32(val) * 1000; - *has_dst = true; - } -} -#endif - -#if defined(CONFIG_AUDIO_ALSA) || defined(CONFIG_AUDIO_COREAUDIO) || \ - defined(CONFIG_AUDIO_PA) || defined(CONFIG_AUDIO_SDL) || \ - defined(CONFIG_AUDIO_DSOUND) || defined(CONFIG_AUDIO_OSS) -static uint32_t frames_to_usecs(uint32_t frames, - AudiodevPerDirectionOptions *pdo) -{ - uint32_t freq = pdo->has_frequency ? pdo->frequency : 44100; - return (frames * 1000000 + freq / 2) / freq; -} -#endif - -#ifdef CONFIG_AUDIO_COREAUDIO -static void get_frames_to_usecs(const char *env, uint32_t *dst, bool *has_dst, - AudiodevPerDirectionOptions *pdo) -{ - const char *val = getenv(env); - if (val) { - *dst = frames_to_usecs(toui32(val), pdo); - *has_dst = true; - } -} -#endif - -#if defined(CONFIG_AUDIO_PA) || defined(CONFIG_AUDIO_SDL) || \ - defined(CONFIG_AUDIO_DSOUND) || defined(CONFIG_AUDIO_OSS) -static uint32_t samples_to_usecs(uint32_t samples, - AudiodevPerDirectionOptions *pdo) -{ - uint32_t channels = pdo->has_channels ? pdo->channels : 2; - return frames_to_usecs(samples / channels, pdo); -} -#endif - -#if defined(CONFIG_AUDIO_PA) || defined(CONFIG_AUDIO_SDL) -static void get_samples_to_usecs(const char *env, uint32_t *dst, bool *has_dst, - AudiodevPerDirectionOptions *pdo) -{ - const char *val = getenv(env); - if (val) { - *dst = samples_to_usecs(toui32(val), pdo); - *has_dst = true; - } -} -#endif - -#if defined(CONFIG_AUDIO_DSOUND) || defined(CONFIG_AUDIO_OSS) -static uint32_t bytes_to_usecs(uint32_t bytes, AudiodevPerDirectionOptions *pdo) -{ - AudioFormat fmt = pdo->has_format ? pdo->format : AUDIO_FORMAT_S16; - uint32_t bytes_per_sample = audioformat_bytes_per_sample(fmt); - return samples_to_usecs(bytes / bytes_per_sample, pdo); -} - -static void get_bytes_to_usecs(const char *env, uint32_t *dst, bool *has_dst, - AudiodevPerDirectionOptions *pdo) -{ - const char *val = getenv(env); - if (val) { - *dst = bytes_to_usecs(toui32(val), pdo); - *has_dst = true; - } -} -#endif - -/* backend specific functions */ - -#ifdef CONFIG_AUDIO_ALSA -/* ALSA */ -static void handle_alsa_per_direction( - AudiodevAlsaPerDirectionOptions *apdo, const char *prefix) -{ - char buf[64]; - size_t len = strlen(prefix); - bool size_in_usecs = false; - bool dummy; - - memcpy(buf, prefix, len); - strcpy(buf + len, "TRY_POLL"); - get_bool(buf, &apdo->try_poll, &apdo->has_try_poll); - - strcpy(buf + len, "DEV"); - get_str(buf, &apdo->dev); - - strcpy(buf + len, "SIZE_IN_USEC"); - get_bool(buf, &size_in_usecs, &dummy); - - strcpy(buf + len, "PERIOD_SIZE"); - get_int(buf, &apdo->period_length, &apdo->has_period_length); - if (apdo->has_period_length && !size_in_usecs) { - apdo->period_length = frames_to_usecs( - apdo->period_length, - qapi_AudiodevAlsaPerDirectionOptions_base(apdo)); - } - - strcpy(buf + len, "BUFFER_SIZE"); - get_int(buf, &apdo->buffer_length, &apdo->has_buffer_length); - if (apdo->has_buffer_length && !size_in_usecs) { - apdo->buffer_length = frames_to_usecs( - apdo->buffer_length, - qapi_AudiodevAlsaPerDirectionOptions_base(apdo)); - } -} - -static void handle_alsa(Audiodev *dev) -{ - AudiodevAlsaOptions *aopt = &dev->u.alsa; - handle_alsa_per_direction(aopt->in, "QEMU_ALSA_ADC_"); - handle_alsa_per_direction(aopt->out, "QEMU_ALSA_DAC_"); - - get_millis_to_usecs("QEMU_ALSA_THRESHOLD", - &aopt->threshold, &aopt->has_threshold); -} -#endif - -#ifdef CONFIG_AUDIO_COREAUDIO -/* coreaudio */ -static void handle_coreaudio(Audiodev *dev) -{ - get_frames_to_usecs( - "QEMU_COREAUDIO_BUFFER_SIZE", - &dev->u.coreaudio.out->buffer_length, - &dev->u.coreaudio.out->has_buffer_length, - qapi_AudiodevCoreaudioPerDirectionOptions_base(dev->u.coreaudio.out)); - get_int("QEMU_COREAUDIO_BUFFER_COUNT", - &dev->u.coreaudio.out->buffer_count, - &dev->u.coreaudio.out->has_buffer_count); -} -#endif - -#ifdef CONFIG_AUDIO_DSOUND -/* dsound */ -static void handle_dsound(Audiodev *dev) -{ - get_millis_to_usecs("QEMU_DSOUND_LATENCY_MILLIS", - &dev->u.dsound.latency, &dev->u.dsound.has_latency); - get_bytes_to_usecs("QEMU_DSOUND_BUFSIZE_OUT", - &dev->u.dsound.out->buffer_length, - &dev->u.dsound.out->has_buffer_length, - dev->u.dsound.out); - get_bytes_to_usecs("QEMU_DSOUND_BUFSIZE_IN", - &dev->u.dsound.in->buffer_length, - &dev->u.dsound.in->has_buffer_length, - dev->u.dsound.in); -} -#endif - -#ifdef CONFIG_AUDIO_OSS -/* OSS */ -static void handle_oss_per_direction( - AudiodevOssPerDirectionOptions *opdo, const char *try_poll_env, - const char *dev_env) -{ - get_bool(try_poll_env, &opdo->try_poll, &opdo->has_try_poll); - get_str(dev_env, &opdo->dev); - - get_bytes_to_usecs("QEMU_OSS_FRAGSIZE", - &opdo->buffer_length, &opdo->has_buffer_length, - qapi_AudiodevOssPerDirectionOptions_base(opdo)); - get_int("QEMU_OSS_NFRAGS", &opdo->buffer_count, - &opdo->has_buffer_count); -} - -static void handle_oss(Audiodev *dev) -{ - AudiodevOssOptions *oopt = &dev->u.oss; - handle_oss_per_direction(oopt->in, "QEMU_AUDIO_ADC_TRY_POLL", - "QEMU_OSS_ADC_DEV"); - handle_oss_per_direction(oopt->out, "QEMU_AUDIO_DAC_TRY_POLL", - "QEMU_OSS_DAC_DEV"); - - get_bool("QEMU_OSS_MMAP", &oopt->try_mmap, &oopt->has_try_mmap); - get_bool("QEMU_OSS_EXCLUSIVE", &oopt->exclusive, &oopt->has_exclusive); - get_int("QEMU_OSS_POLICY", &oopt->dsp_policy, &oopt->has_dsp_policy); -} -#endif - -#ifdef CONFIG_AUDIO_PA -/* pulseaudio */ -static void handle_pa_per_direction( - AudiodevPaPerDirectionOptions *ppdo, const char *env) -{ - get_str(env, &ppdo->name); -} - -static void handle_pa(Audiodev *dev) -{ - handle_pa_per_direction(dev->u.pa.in, "QEMU_PA_SOURCE"); - handle_pa_per_direction(dev->u.pa.out, "QEMU_PA_SINK"); - - get_samples_to_usecs( - "QEMU_PA_SAMPLES", &dev->u.pa.in->buffer_length, - &dev->u.pa.in->has_buffer_length, - qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.in)); - get_samples_to_usecs( - "QEMU_PA_SAMPLES", &dev->u.pa.out->buffer_length, - &dev->u.pa.out->has_buffer_length, - qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.out)); - - get_str("QEMU_PA_SERVER", &dev->u.pa.server); -} -#endif - -#ifdef CONFIG_AUDIO_SDL -/* SDL */ -static void handle_sdl(Audiodev *dev) -{ - /* SDL is output only */ - get_samples_to_usecs("QEMU_SDL_SAMPLES", &dev->u.sdl.out->buffer_length, - &dev->u.sdl.out->has_buffer_length, - qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.out)); -} -#endif - -/* wav */ -static void handle_wav(Audiodev *dev) -{ - get_int("QEMU_WAV_FREQUENCY", - &dev->u.wav.out->frequency, &dev->u.wav.out->has_frequency); - get_fmt("QEMU_WAV_FORMAT", &dev->u.wav.out->format, - &dev->u.wav.out->has_format); - get_int("QEMU_WAV_DAC_FIXED_CHANNELS", - &dev->u.wav.out->channels, &dev->u.wav.out->has_channels); - get_str("QEMU_WAV_PATH", &dev->u.wav.path); -} - -/* general */ -static void handle_per_direction( - AudiodevPerDirectionOptions *pdo, const char *prefix) -{ - char buf[64]; - size_t len = strlen(prefix); - - memcpy(buf, prefix, len); - strcpy(buf + len, "FIXED_SETTINGS"); - get_bool(buf, &pdo->fixed_settings, &pdo->has_fixed_settings); - - strcpy(buf + len, "FIXED_FREQ"); - get_int(buf, &pdo->frequency, &pdo->has_frequency); - - strcpy(buf + len, "FIXED_FMT"); - get_fmt(buf, &pdo->format, &pdo->has_format); - - strcpy(buf + len, "FIXED_CHANNELS"); - get_int(buf, &pdo->channels, &pdo->has_channels); - - strcpy(buf + len, "VOICES"); - get_int(buf, &pdo->voices, &pdo->has_voices); -} - -static AudiodevListEntry *legacy_opt(const char *drvname) -{ - AudiodevListEntry *e = g_new0(AudiodevListEntry, 1); - e->dev = g_new0(Audiodev, 1); - e->dev->id = g_strdup(drvname); - e->dev->driver = qapi_enum_parse( - &AudiodevDriver_lookup, drvname, -1, &error_abort); - - audio_create_pdos(e->dev); - - handle_per_direction(audio_get_pdo_in(e->dev), "QEMU_AUDIO_ADC_"); - handle_per_direction(audio_get_pdo_out(e->dev), "QEMU_AUDIO_DAC_"); - - /* Original description: Timer period in HZ (0 - use lowest possible) */ - get_int("QEMU_AUDIO_TIMER_PERIOD", - &e->dev->timer_period, &e->dev->has_timer_period); - if (e->dev->has_timer_period && e->dev->timer_period) { - e->dev->timer_period = NANOSECONDS_PER_SECOND / 1000 / - e->dev->timer_period; - } - - switch (e->dev->driver) { -#ifdef CONFIG_AUDIO_ALSA - case AUDIODEV_DRIVER_ALSA: - handle_alsa(e->dev); - break; -#endif - -#ifdef CONFIG_AUDIO_COREAUDIO - case AUDIODEV_DRIVER_COREAUDIO: - handle_coreaudio(e->dev); - break; -#endif - -#ifdef CONFIG_AUDIO_DSOUND - case AUDIODEV_DRIVER_DSOUND: - handle_dsound(e->dev); - break; -#endif - -#ifdef CONFIG_AUDIO_OSS - case AUDIODEV_DRIVER_OSS: - handle_oss(e->dev); - break; -#endif - -#ifdef CONFIG_AUDIO_PA - case AUDIODEV_DRIVER_PA: - handle_pa(e->dev); - break; -#endif - -#ifdef CONFIG_AUDIO_SDL - case AUDIODEV_DRIVER_SDL: - handle_sdl(e->dev); - break; -#endif - - case AUDIODEV_DRIVER_WAV: - handle_wav(e->dev); - break; - - default: - break; - } - - return e; -} - -AudiodevListHead audio_handle_legacy_opts(void) -{ - const char *drvname = getenv("QEMU_AUDIO_DRV"); - AudiodevListHead head = QSIMPLEQ_HEAD_INITIALIZER(head); - - if (drvname) { - AudiodevListEntry *e; - audio_driver *driver = audio_driver_lookup(drvname); - if (!driver) { - dolog("Unknown audio driver `%s'\n", drvname); - exit(1); - } - e = legacy_opt(drvname); - QSIMPLEQ_INSERT_TAIL(&head, e, next); - } else { - for (int i = 0; audio_prio_list[i]; i++) { - audio_driver *driver = audio_driver_lookup(audio_prio_list[i]); - if (driver && driver->can_be_default) { - AudiodevListEntry *e = legacy_opt(driver->name); - QSIMPLEQ_INSERT_TAIL(&head, e, next); - } - } - if (QSIMPLEQ_EMPTY(&head)) { - dolog("Internal error: no default audio driver available\n"); - exit(1); - } - } - - return head; -} - -/* visitor to print -audiodev option */ -typedef struct { - Visitor visitor; - - bool comma; - GList *path; -} LegacyPrintVisitor; - -static bool lv_start_struct(Visitor *v, const char *name, void **obj, - size_t size, Error **errp) -{ - LegacyPrintVisitor *lv = (LegacyPrintVisitor *) v; - lv->path = g_list_append(lv->path, g_strdup(name)); - return true; -} - -static void lv_end_struct(Visitor *v, void **obj) -{ - LegacyPrintVisitor *lv = (LegacyPrintVisitor *) v; - lv->path = g_list_delete_link(lv->path, g_list_last(lv->path)); -} - -static void lv_print_key(Visitor *v, const char *name) -{ - GList *e; - LegacyPrintVisitor *lv = (LegacyPrintVisitor *) v; - if (lv->comma) { - putchar(','); - } else { - lv->comma = true; - } - - for (e = lv->path; e; e = e->next) { - if (e->data) { - printf("%s.", (const char *) e->data); - } - } - - printf("%s=", name); -} - -static bool lv_type_int64(Visitor *v, const char *name, int64_t *obj, - Error **errp) -{ - lv_print_key(v, name); - printf("%" PRIi64, *obj); - return true; -} - -static bool lv_type_uint64(Visitor *v, const char *name, uint64_t *obj, - Error **errp) -{ - lv_print_key(v, name); - printf("%" PRIu64, *obj); - return true; -} - -static bool lv_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) -{ - lv_print_key(v, name); - printf("%s", *obj ? "on" : "off"); - return true; -} - -static bool lv_type_str(Visitor *v, const char *name, char **obj, Error **errp) -{ - const char *str = *obj; - lv_print_key(v, name); - - while (*str) { - if (*str == ',') { - putchar(','); - } - putchar(*str++); - } - return true; -} - -static void lv_complete(Visitor *v, void *opaque) -{ - LegacyPrintVisitor *lv = (LegacyPrintVisitor *) v; - assert(lv->path == NULL); -} - -static void lv_free(Visitor *v) -{ - LegacyPrintVisitor *lv = (LegacyPrintVisitor *) v; - - g_list_free_full(lv->path, g_free); - g_free(lv); -} - -static Visitor *legacy_visitor_new(void) -{ - LegacyPrintVisitor *lv = g_new0(LegacyPrintVisitor, 1); - - lv->visitor.start_struct = lv_start_struct; - lv->visitor.end_struct = lv_end_struct; - /* lists not supported */ - lv->visitor.type_int64 = lv_type_int64; - lv->visitor.type_uint64 = lv_type_uint64; - lv->visitor.type_bool = lv_type_bool; - lv->visitor.type_str = lv_type_str; - - lv->visitor.type = VISITOR_OUTPUT; - lv->visitor.complete = lv_complete; - lv->visitor.free = lv_free; - - return &lv->visitor; -} - -void audio_legacy_help(void) -{ - AudiodevListHead head; - AudiodevListEntry *e; - - printf("Environment variable based configuration deprecated.\n"); - printf("Please use the new -audiodev option.\n"); - - head = audio_handle_legacy_opts(); - printf("\nEquivalent -audiodev to your current environment variables:\n"); - if (!getenv("QEMU_AUDIO_DRV")) { - printf("(Since you didn't specify QEMU_AUDIO_DRV, I'll list all " - "possibilities)\n"); - } - - QSIMPLEQ_FOREACH(e, &head, next) { - Visitor *v; - Audiodev *dev = e->dev; - printf("-audiodev "); - - v = legacy_visitor_new(); - visit_type_Audiodev(v, NULL, &dev, &error_abort); - visit_free(v); - - printf("\n"); - } - audio_free_audiodev_list(&head); -} diff --git a/audio/coreaudio.m b/audio/coreaudio.m index 7cfb38fb6ae3..8cd129a27d02 100644 --- a/audio/coreaudio.m +++ b/audio/coreaudio.m @@ -673,7 +673,6 @@ static void coreaudio_audio_fini (void *opaque) .init = coreaudio_audio_init, .fini = coreaudio_audio_fini, .pcm_ops = &coreaudio_pcm_ops, - .can_be_default = 1, .max_voices_out = 1, .max_voices_in = 0, .voice_size_out = sizeof (coreaudioVoiceOut), diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index 310ca997ff41..60fcf643ecf8 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -676,7 +676,6 @@ static struct audio_driver dbus_audio_driver = { .fini = dbus_audio_fini, .set_dbus_server = dbus_audio_set_server, .pcm_ops = &dbus_pcm_ops, - .can_be_default = 1, .max_voices_out = INT_MAX, .max_voices_in = INT_MAX, .voice_size_out = sizeof(DBusVoiceOut), diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index eefde88edcb1..f3bb48d00737 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -721,7 +721,6 @@ static struct audio_driver dsound_audio_driver = { .init = dsound_audio_init, .fini = dsound_audio_fini, .pcm_ops = &dsound_pcm_ops, - .can_be_default = 1, .max_voices_out = INT_MAX, .max_voices_in = 1, .voice_size_out = sizeof (DSoundVoiceOut), diff --git a/audio/jackaudio.c b/audio/jackaudio.c index 823e7d96baee..974a3caad347 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -676,7 +676,6 @@ static struct audio_driver jack_driver = { .init = qjack_init, .fini = qjack_fini, .pcm_ops = &jack_pcm_ops, - .can_be_default = 1, .max_voices_out = INT_MAX, .max_voices_in = INT_MAX, .voice_size_out = sizeof(QJackOut), diff --git a/audio/meson.build b/audio/meson.build index df4d968c0fe5..c8f658611f42 100644 --- a/audio/meson.build +++ b/audio/meson.build @@ -1,7 +1,6 @@ system_ss.add([spice_headers, files('audio.c')]) system_ss.add(files( 'audio-hmp-cmds.c', - 'audio_legacy.c', 'mixeng.c', 'noaudio.c', 'wavaudio.c', diff --git a/audio/noaudio.c b/audio/noaudio.c index a36bfeffd14b..1b60d8518a44 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -135,7 +135,6 @@ static struct audio_driver no_audio_driver = { .init = no_audio_init, .fini = no_audio_fini, .pcm_ops = &no_pcm_ops, - .can_be_default = 1, .max_voices_out = INT_MAX, .max_voices_in = INT_MAX, .voice_size_out = sizeof (NoVoiceOut), diff --git a/audio/ossaudio.c b/audio/ossaudio.c index ec4448d573dd..3f31852371d9 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -784,7 +784,6 @@ static struct audio_driver oss_audio_driver = { .init = oss_audio_init, .fini = oss_audio_fini, .pcm_ops = &oss_pcm_ops, - .can_be_default = 1, .max_voices_out = INT_MAX, .max_voices_in = INT_MAX, .voice_size_out = sizeof (OSSVoiceOut), diff --git a/audio/paaudio.c b/audio/paaudio.c index 39bd6cfa38a5..f3193b08c32a 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -931,7 +931,6 @@ static struct audio_driver pa_audio_driver = { .init = qpa_audio_init, .fini = qpa_audio_fini, .pcm_ops = &qpa_pcm_ops, - .can_be_default = 1, .max_voices_out = INT_MAX, .max_voices_in = INT_MAX, .voice_size_out = sizeof (PAVoiceOut), diff --git a/audio/pwaudio.c b/audio/pwaudio.c index 1020cb11df1b..3ce5f6507b47 100644 --- a/audio/pwaudio.c +++ b/audio/pwaudio.c @@ -843,7 +843,6 @@ static struct audio_driver pw_audio_driver = { .init = qpw_audio_init, .fini = qpw_audio_fini, .pcm_ops = &qpw_pcm_ops, - .can_be_default = 1, .max_voices_out = INT_MAX, .max_voices_in = INT_MAX, .voice_size_out = sizeof(PWVoiceOut), diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index 4d8473d9ece8..641357e5ee38 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -494,7 +494,6 @@ static struct audio_driver sdl_audio_driver = { .init = sdl_audio_init, .fini = sdl_audio_fini, .pcm_ops = &sdl_pcm_ops, - .can_be_default = 1, .max_voices_out = INT_MAX, .max_voices_in = INT_MAX, .voice_size_out = sizeof(SDLVoiceOut), diff --git a/audio/sndioaudio.c b/audio/sndioaudio.c index 1e35925a497e..8eb35e1e5386 100644 --- a/audio/sndioaudio.c +++ b/audio/sndioaudio.c @@ -550,7 +550,6 @@ static struct audio_driver sndio_audio_driver = { .init = sndio_audio_init, .fini = sndio_audio_fini, .pcm_ops = &sndio_pcm_ops, - .can_be_default = 1, .max_voices_out = INT_MAX, .max_voices_in = INT_MAX, .voice_size_out = sizeof(SndioVoice), diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 26b03906d592..ea20fed0ccb9 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -208,7 +208,6 @@ static struct audio_driver wav_audio_driver = { .init = wav_audio_init, .fini = wav_audio_fini, .pcm_ops = &wav_pcm_ops, - .can_be_default = 0, .max_voices_out = 1, .max_voices_in = 0, .voice_size_out = sizeof (WAVVoiceOut), diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index c07bf58dde18..2f51cf770ae6 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -37,14 +37,6 @@ coverage. System emulator command line arguments -------------------------------------- -``QEMU_AUDIO_`` environment variables and ``-audio-help`` (since 4.0) -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -The ``-audiodev`` argument is now the preferred way to specify audio -backend settings instead of environment variables. To ease migration to -the new format, the ``-audiodev-help`` option can be used to convert -the current values of the environment variables to ``-audiodev`` options. - Creating sound card devices without ``audiodev=`` property (since 4.2) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index 276060b320c0..e83ed087f6b1 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -436,6 +436,12 @@ the process listing. This was replaced by the new ``password-secret`` option which lets the password be securely provided on the command line using a ``secret`` object instance. +``QEMU_AUDIO_`` environment variables and ``-audio-help`` (removed in 8.2) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The ``-audiodev`` and ``-audio`` command line options are now the only +way to specify audio backend settings. + Creating vnc without ``audiodev=`` property (removed in 8.2) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' diff --git a/qemu-options.hx b/qemu-options.hx index bcd77255cbda..9ce8a5b95784 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -727,16 +727,6 @@ SRST ERST -HXCOMM Deprecated by -audiodev -DEF("audio-help", 0, QEMU_OPTION_audio_help, - "-audio-help show -audiodev equivalent of the currently specified audio settings\n", - QEMU_ARCH_ALL) -SRST -``-audio-help`` - Will show the -audiodev equivalent of the currently specified - (deprecated) environment variables. -ERST - DEF("audio", HAS_ARG, QEMU_OPTION_audio, "-audio [driver=]driver,model=value[,prop[=value][,...]]\n" " specifies the audio backend and device to use;\n" diff --git a/softmmu/vl.c b/softmmu/vl.c index 59a472a0b108..cafb1a98427d 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2926,10 +2926,6 @@ void qemu_init(int argc, char **argv) } break; #endif - case QEMU_OPTION_audio_help: - audio_legacy_help(); - exit (0); - break; case QEMU_OPTION_audiodev: audio_parse_option(optarg); break; From 7a2c7da6448eb8538bccbbc288508bde69bc4c2d Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Mon, 25 Apr 2022 10:21:50 +0200 Subject: [PATCH 124/208] Introduce machine property "audiodev" Many machine types have default audio devices with no way to set the underlying audiodev. Instead of adding an option for each and every one of them, this new property can be used as a default during machine initialisation when creating such devices. Signed-off-by: Martin Kletzander [Make the property optional, instead of including it in all machines. - Paolo] Signed-off-by: Paolo Bonzini --- hw/core/machine.c | 33 +++++++++++++++++++++++++++++++++ include/hw/boards.h | 9 +++++++++ 2 files changed, 42 insertions(+) diff --git a/hw/core/machine.c b/hw/core/machine.c index cb38b8cf4cb4..6aa49c8d4f13 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -39,6 +39,7 @@ #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-pci.h" #include "hw/virtio/virtio-net.h" +#include "audio/audio.h" GlobalProperty hw_compat_8_1[] = {}; const size_t hw_compat_8_1_len = G_N_ELEMENTS(hw_compat_8_1); @@ -686,6 +687,26 @@ bool device_type_is_dynamic_sysbus(MachineClass *mc, const char *type) return allowed; } +static char *machine_get_audiodev(Object *obj, Error **errp) +{ + MachineState *ms = MACHINE(obj); + + return g_strdup(ms->audiodev); +} + +static void machine_set_audiodev(Object *obj, const char *value, + Error **errp) +{ + MachineState *ms = MACHINE(obj); + + if (!audio_state_by_name(value, errp)) { + return; + } + + g_free(ms->audiodev); + ms->audiodev = g_strdup(value); +} + HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine) { int i; @@ -931,6 +952,17 @@ static void machine_set_boot(Object *obj, Visitor *v, const char *name, qapi_free_BootConfiguration(config); } +void machine_add_audiodev_property(MachineClass *mc) +{ + ObjectClass *oc = OBJECT_CLASS(mc); + + object_class_property_add_str(oc, "audiodev", + machine_get_audiodev, + machine_set_audiodev); + object_class_property_set_description(oc, "audiodev", + "Audiodev to use for default machine devices"); +} + static void machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1136,6 +1168,7 @@ static void machine_finalize(Object *obj) g_free(ms->device_memory); g_free(ms->nvdimms_state); g_free(ms->numa_state); + g_free(ms->audiodev); } bool machine_usb(MachineState *machine) diff --git a/include/hw/boards.h b/include/hw/boards.h index 6c67af196a3f..55a64a13fdfe 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -24,6 +24,7 @@ OBJECT_DECLARE_TYPE(MachineState, MachineClass, MACHINE) extern MachineState *current_machine; +void machine_add_audiodev_property(MachineClass *mc); void machine_run_board_init(MachineState *machine, const char *mem_path, Error **errp); bool machine_usb(MachineState *machine); int machine_phandle_start(MachineState *machine); @@ -358,6 +359,14 @@ struct MachineState { MemoryRegion *ram; DeviceMemoryState *device_memory; + /* + * Included in MachineState for simplicity, but not supported + * unless machine_add_audiodev_property is called. Boards + * that have embedded audio devices can call it from the + * machine init function and forward the property to the device. + */ + char *audiodev; + ram_addr_t ram_size; ram_addr_t maxram_size; uint64_t ram_slots; From b8ab0303de5a72d89da5ab25d8fe817d8797888f Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Fri, 22 Sep 2023 17:21:39 +0200 Subject: [PATCH 125/208] hw/arm: Support machine-default audiodev with fallback Signed-off-by: Martin Kletzander Signed-off-by: Paolo Bonzini --- hw/arm/integratorcp.c | 11 ++++++++++- hw/arm/musicpal.c | 11 +++++++++-- hw/arm/nseries.c | 4 ++++ hw/arm/omap2.c | 5 +++++ hw/arm/palm.c | 2 ++ hw/arm/realview.c | 12 ++++++++++++ hw/arm/spitz.c | 17 ++++++++++++----- hw/arm/versatilepb.c | 8 ++++++++ hw/arm/vexpress.c | 5 +++++ hw/arm/xlnx-zcu102.c | 6 ++++++ hw/arm/z2.c | 15 ++++++++++++++- hw/input/tsc210x.c | 5 +++++ 12 files changed, 92 insertions(+), 9 deletions(-) diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c index b109ece3ae02..d176e9af7eee 100644 --- a/hw/arm/integratorcp.c +++ b/hw/arm/integratorcp.c @@ -27,6 +27,7 @@ #include "hw/irq.h" #include "hw/sd/sd.h" #include "qom/object.h" +#include "audio/audio.h" #define TYPE_INTEGRATOR_CM "integrator_core" OBJECT_DECLARE_SIMPLE_TYPE(IntegratorCMState, INTEGRATOR_CM) @@ -660,7 +661,13 @@ static void integratorcp_init(MachineState *machine) &error_fatal); } - sysbus_create_varargs("pl041", 0x1d000000, pic[25], NULL); + dev = qdev_new("pl041"); + if (machine->audiodev) { + qdev_prop_set_string(dev, "audiodev", machine->audiodev); + } + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x1d000000); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[25]); if (nd_table[0].used) smc91c111_init(&nd_table[0], 0xc8000000, pic[27]); @@ -678,6 +685,8 @@ static void integratorcp_machine_init(MachineClass *mc) mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926"); mc->default_ram_id = "integrator.ram"; + + machine_add_audiodev_property(mc); } DEFINE_MACHINE("integratorcp", integratorcp_machine_init) diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index dc4e43e0ee2e..9703bfb97fb4 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -37,9 +37,9 @@ #include "qemu/cutils.h" #include "qom/object.h" #include "hw/net/mv88w8618_eth.h" +#include "audio/audio.h" #include "qemu/error-report.h" - #define MP_MISC_BASE 0x80002000 #define MP_MISC_SIZE 0x00001000 @@ -1326,7 +1326,12 @@ static void musicpal_init(MachineState *machine) qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15)); } - wm8750_dev = i2c_slave_create_simple(i2c, TYPE_WM8750, MP_WM_ADDR); + wm8750_dev = i2c_slave_new(TYPE_WM8750, MP_WM_ADDR); + if (machine->audiodev) { + qdev_prop_set_string(DEVICE(wm8750_dev), "audiodev", machine->audiodev); + } + i2c_slave_realize_and_unref(wm8750_dev, i2c, &error_abort); + dev = qdev_new(TYPE_MV88W8618_AUDIO); s = SYS_BUS_DEVICE(dev); object_property_set_link(OBJECT(dev), "wm8750", OBJECT(wm8750_dev), @@ -1347,6 +1352,8 @@ static void musicpal_machine_init(MachineClass *mc) mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926"); mc->default_ram_size = MP_RAM_DEFAULT_SIZE; mc->default_ram_id = "musicpal.ram"; + + machine_add_audiodev_property(mc); } DEFINE_MACHINE("musicpal", musicpal_machine_init) diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index 9e49e9e17762..35aff46b4b48 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -1432,6 +1432,8 @@ static void n800_class_init(ObjectClass *oc, void *data) /* Actually two chips of 0x4000000 bytes each */ mc->default_ram_size = 0x08000000; mc->default_ram_id = "omap2.dram"; + + machine_add_audiodev_property(mc); } static const TypeInfo n800_type = { @@ -1452,6 +1454,8 @@ static void n810_class_init(ObjectClass *oc, void *data) /* Actually two chips of 0x4000000 bytes each */ mc->default_ram_size = 0x08000000; mc->default_ram_id = "omap2.dram"; + + machine_add_audiodev_property(mc); } static const TypeInfo n810_type = { diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c index d5a2ae7af6ed..41b1f596dcac 100644 --- a/hw/arm/omap2.c +++ b/hw/arm/omap2.c @@ -37,6 +37,7 @@ #include "hw/block/flash.h" #include "hw/arm/soc_dma.h" #include "hw/sysbus.h" +#include "hw/boards.h" #include "audio/audio.h" /* Enhanced Audio Controller (CODEC only) */ @@ -609,6 +610,10 @@ static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta, s->codec.txdrq = *drq; omap_eac_reset(s); + if (current_machine->audiodev) { + s->codec.card.name = g_strdup(current_machine->audiodev); + s->codec.card.state = audio_state_by_name(s->codec.card.name, &error_fatal); + } AUD_register_card("OMAP EAC", &s->codec.card); memory_region_init_io(&s->iomem, NULL, &omap_eac_ops, s, "omap.eac", diff --git a/hw/arm/palm.c b/hw/arm/palm.c index 17c11ac4ceca..b86f2c331bb9 100644 --- a/hw/arm/palm.c +++ b/hw/arm/palm.c @@ -310,6 +310,8 @@ static void palmte_machine_init(MachineClass *mc) mc->default_cpu_type = ARM_CPU_TYPE_NAME("ti925t"); mc->default_ram_size = 0x02000000; mc->default_ram_id = "omap1.dram"; + + machine_add_audiodev_property(mc); } DEFINE_MACHINE("cheetah", palmte_machine_init) diff --git a/hw/arm/realview.c b/hw/arm/realview.c index a5aa2f046aec..8f89526596c1 100644 --- a/hw/arm/realview.c +++ b/hw/arm/realview.c @@ -29,6 +29,7 @@ #include "hw/irq.h" #include "hw/i2c/arm_sbcon_i2c.h" #include "hw/sd/sd.h" +#include "audio/audio.h" #define SMP_BOOT_ADDR 0xe0000000 #define SMP_BOOTREG_ADDR 0x10000030 @@ -207,6 +208,9 @@ static void realview_init(MachineState *machine, pl041 = qdev_new("pl041"); qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512); + if (machine->audiodev) { + qdev_prop_set_string(pl041, "audiodev", machine->audiodev); + } sysbus_realize_and_unref(SYS_BUS_DEVICE(pl041), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000); sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[19]); @@ -412,6 +416,8 @@ static void realview_eb_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_SCSI; mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926"); + + machine_add_audiodev_property(mc); } static const TypeInfo realview_eb_type = { @@ -430,6 +436,8 @@ static void realview_eb_mpcore_class_init(ObjectClass *oc, void *data) mc->max_cpus = 4; mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm11mpcore"); + + machine_add_audiodev_property(mc); } static const TypeInfo realview_eb_mpcore_type = { @@ -446,6 +454,8 @@ static void realview_pb_a8_class_init(ObjectClass *oc, void *data) mc->init = realview_pb_a8_init; mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a8"); + + machine_add_audiodev_property(mc); } static const TypeInfo realview_pb_a8_type = { @@ -463,6 +473,8 @@ static void realview_pbx_a9_class_init(ObjectClass *oc, void *data) mc->max_cpus = 4; mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a9"); + + machine_add_audiodev_property(mc); } static const TypeInfo realview_pbx_a9_type = { diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index f732fe0acf90..cc268c6ac0b7 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -35,6 +35,7 @@ #include "exec/address-spaces.h" #include "cpu.h" #include "qom/object.h" +#include "audio/audio.h" enum spitz_model_e { spitz, akita, borzoi, terrier }; @@ -774,15 +775,19 @@ static void spitz_wm8750_addr(void *opaque, int line, int level) i2c_slave_set_address(wm, SPITZ_WM_ADDRL); } -static void spitz_i2c_setup(PXA2xxState *cpu) +static void spitz_i2c_setup(MachineState *machine, PXA2xxState *cpu) { /* Attach the CPU on one end of our I2C bus. */ I2CBus *bus = pxa2xx_i2c_bus(cpu->i2c[0]); - DeviceState *wm; - /* Attach a WM8750 to the bus */ - wm = DEVICE(i2c_slave_create_simple(bus, TYPE_WM8750, 0)); + I2CSlave *i2c_dev = i2c_slave_new(TYPE_WM8750, 0); + DeviceState *wm = DEVICE(i2c_dev); + + if (machine->audiodev) { + qdev_prop_set_string(wm, "audiodev", machine->audiodev); + } + i2c_slave_realize_and_unref(i2c_dev, bus, &error_abort); spitz_wm8750_addr(wm, 0, 0); qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_WM, @@ -1013,7 +1018,7 @@ static void spitz_common_init(MachineState *machine) spitz_gpio_setup(mpu, (model == akita) ? 1 : 2); - spitz_i2c_setup(mpu); + spitz_i2c_setup(machine, mpu); if (model == akita) spitz_akita_i2c_setup(mpu); @@ -1037,6 +1042,8 @@ static void spitz_common_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_IDE; mc->ignore_memory_transaction_failures = true; mc->init = spitz_common_init; + + machine_add_audiodev_property(mc); } static const TypeInfo spitz_common_info = { diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c index 05b9462a5b79..2f22dc890f4c 100644 --- a/hw/arm/versatilepb.c +++ b/hw/arm/versatilepb.c @@ -26,6 +26,7 @@ #include "hw/char/pl011.h" #include "hw/sd/sd.h" #include "qom/object.h" +#include "audio/audio.h" #define VERSATILE_FLASH_ADDR 0x34000000 #define VERSATILE_FLASH_SIZE (64 * 1024 * 1024) @@ -343,6 +344,9 @@ static void versatile_init(MachineState *machine, int board_id) /* Add PL041 AACI Interface to the LM4549 codec */ pl041 = qdev_new("pl041"); qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512); + if (machine->audiodev) { + qdev_prop_set_string(pl041, "audiodev", machine->audiodev); + } sysbus_realize_and_unref(SYS_BUS_DEVICE(pl041), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000); sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, sic[24]); @@ -416,6 +420,8 @@ static void versatilepb_class_init(ObjectClass *oc, void *data) mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926"); mc->default_ram_id = "versatile.ram"; + + machine_add_audiodev_property(mc); } static const TypeInfo versatilepb_type = { @@ -434,6 +440,8 @@ static void versatileab_class_init(ObjectClass *oc, void *data) mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926"); mc->default_ram_id = "versatile.ram"; + + machine_add_audiodev_property(mc); } static const TypeInfo versatileab_type = { diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index 56abadd9b8bb..8ff37f52ca10 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -44,6 +44,7 @@ #include "hw/i2c/arm_sbcon_i2c.h" #include "hw/sd/sd.h" #include "qom/object.h" +#include "audio/audio.h" #define VEXPRESS_BOARD_ID 0x8e0 #define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024) @@ -613,6 +614,9 @@ static void vexpress_common_init(MachineState *machine) pl041 = qdev_new("pl041"); qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512); + if (machine->audiodev) { + qdev_prop_set_string(pl041, "audiodev", machine->audiodev); + } sysbus_realize_and_unref(SYS_BUS_DEVICE(pl041), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, map[VE_PL041]); sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[11]); @@ -776,6 +780,7 @@ static void vexpress_class_init(ObjectClass *oc, void *data) mc->ignore_memory_transaction_failures = true; mc->default_ram_id = "vexpress.highmem"; + machine_add_audiodev_property(mc); object_class_property_add_bool(oc, "secure", vexpress_get_secure, vexpress_set_secure); object_class_property_set_description(oc, "secure", diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c index 21483f75fd93..c5a07cfe1952 100644 --- a/hw/arm/xlnx-zcu102.c +++ b/hw/arm/xlnx-zcu102.c @@ -24,6 +24,7 @@ #include "sysemu/device_tree.h" #include "qom/object.h" #include "net/can_emu.h" +#include "audio/audio.h" struct XlnxZCU102 { MachineState parent_obj; @@ -143,6 +144,10 @@ static void xlnx_zcu102_init(MachineState *machine) object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_XLNX_ZYNQMP); + if (machine->audiodev) { + qdev_prop_set_string(DEVICE(&s->soc.dp), "audiodev", machine->audiodev); + } + object_property_set_link(OBJECT(&s->soc), "ddr-ram", OBJECT(machine->ram), &error_abort); object_property_set_bool(OBJECT(&s->soc), "secure", s->secure, @@ -275,6 +280,7 @@ static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data) mc->default_cpus = XLNX_ZYNQMP_NUM_APU_CPUS; mc->default_ram_id = "ddr-ram"; + machine_add_audiodev_property(mc); object_class_property_add_bool(oc, "secure", zcu102_get_secure, zcu102_set_secure); object_class_property_set_description(oc, "secure", diff --git a/hw/arm/z2.c b/hw/arm/z2.c index dc25304290aa..d9a08fa67b23 100644 --- a/hw/arm/z2.c +++ b/hw/arm/z2.c @@ -27,6 +27,7 @@ #include "exec/address-spaces.h" #include "cpu.h" #include "qom/object.h" +#include "qapi/error.h" #ifdef DEBUG_Z2 #define DPRINTF(fmt, ...) \ @@ -307,6 +308,7 @@ static void z2_init(MachineState *machine) void *z2_lcd; I2CBus *bus; DeviceState *wm; + I2CSlave *i2c_dev; /* Setup CPU & memory */ mpu = pxa270_init(z2_binfo.ram_size, machine->cpu_type); @@ -328,8 +330,17 @@ static void z2_init(MachineState *machine) type_register_static(&aer915_info); z2_lcd = ssi_create_peripheral(mpu->ssp[1], TYPE_ZIPIT_LCD); bus = pxa2xx_i2c_bus(mpu->i2c[0]); + i2c_slave_create_simple(bus, TYPE_AER915, 0x55); - wm = DEVICE(i2c_slave_create_simple(bus, TYPE_WM8750, 0x1b)); + + i2c_dev = i2c_slave_new(TYPE_WM8750, 0x1b); + wm = DEVICE(i2c_dev); + + if (machine->audiodev) { + qdev_prop_set_string(wm, "audiodev", machine->audiodev); + } + i2c_slave_realize_and_unref(i2c_dev, bus, &error_abort); + mpu->i2s->opaque = wm; mpu->i2s->codec_out = wm8750_dac_dat; mpu->i2s->codec_in = wm8750_adc_dat; @@ -348,6 +359,8 @@ static void z2_machine_init(MachineClass *mc) mc->init = z2_init; mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("pxa270-c5"); + + machine_add_audiodev_property(mc); } DEFINE_MACHINE("z2", z2_machine_init) diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c index f568759e05aa..e7960a506960 100644 --- a/hw/input/tsc210x.c +++ b/hw/input/tsc210x.c @@ -27,6 +27,7 @@ #include "sysemu/reset.h" #include "ui/console.h" #include "hw/arm/omap.h" /* For I2SCodec */ +#include "hw/boards.h" /* for current_machine */ #include "hw/input/tsc2xxx.h" #include "hw/irq.h" #include "migration/vmstate.h" @@ -1097,6 +1098,10 @@ static void tsc210x_init(TSC210xState *s, qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1, name); + if (current_machine->audiodev) { + s->card.name = g_strdup(current_machine->audiodev); + s->card.state = audio_state_by_name(s->card.name, &error_fatal); + } AUD_register_card(s->name, &s->card); qemu_register_reset((void *) tsc210x_reset, s); From 2b16397264a8ea4b5274023b22b09a69e92cb8e9 Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Mon, 25 Apr 2022 10:21:55 +0200 Subject: [PATCH 126/208] hw/ppc: Support machine-default audiodev with fallback Signed-off-by: Martin Kletzander Signed-off-by: Paolo Bonzini --- hw/ppc/prep.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index f6fd35fcb9e3..137276bcb92b 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -45,6 +45,7 @@ #include "trace.h" #include "elf.h" #include "qemu/units.h" +#include "audio/audio.h" /* SMP is not enabled, for now */ #define MAX_CPUS 1 @@ -310,6 +311,10 @@ static void ibm_40p_init(MachineState *machine) dev = DEVICE(isa_dev); qdev_prop_set_uint32(dev, "iobase", 0x830); qdev_prop_set_uint32(dev, "irq", 10); + + if (machine->audiodev) { + qdev_prop_set_string(dev, "audiodev", machine->audiodev); + } isa_realize_and_unref(isa_dev, isa_bus, &error_fatal); isa_dev = isa_new("pc87312"); @@ -426,6 +431,8 @@ static void ibm_40p_machine_init(MachineClass *mc) mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("604"); mc->default_display = "std"; mc->default_nic = "pcnet"; + + machine_add_audiodev_property(mc); } DEFINE_MACHINE("40p", ibm_40p_machine_init) From 9dcb64c96073e9898105cdbef6553cfef0fadcdb Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 21 Sep 2023 09:51:04 +0200 Subject: [PATCH 127/208] vt82c686 machines: Support machine-default audiodev with fallback Signed-off-by: Paolo Bonzini --- hw/mips/fuloong2e.c | 15 ++++++++++++--- hw/ppc/pegasos2.c | 12 ++++++++++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index c827f615f3ba..c6109633fee9 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -295,9 +295,17 @@ static void mips_fuloong2e_init(MachineState *machine) pci_bus = bonito_init((qemu_irq *)&(env->irq[2])); /* South bridge -> IP5 */ - pci_dev = pci_create_simple_multifunction(pci_bus, - PCI_DEVFN(FULOONG2E_VIA_SLOT, 0), - TYPE_VT82C686B_ISA); + pci_dev = pci_new_multifunction(PCI_DEVFN(FULOONG2E_VIA_SLOT, 0), + TYPE_VT82C686B_ISA); + + /* Set properties on individual devices before realizing the south bridge */ + if (machine->audiodev) { + dev = DEVICE(object_resolve_path_component(OBJECT(pci_dev), "ac97")); + qdev_prop_set_string(dev, "audiodev", machine->audiodev); + } + + pci_realize_and_unref(pci_dev, pci_bus, &error_abort); + object_property_add_alias(OBJECT(machine), "rtc-time", object_resolve_path_component(OBJECT(pci_dev), "rtc"), @@ -337,6 +345,7 @@ static void mips_fuloong2e_machine_init(MachineClass *mc) mc->default_ram_size = 256 * MiB; mc->default_ram_id = "fuloong2e.ram"; mc->minimum_page_bits = 14; + machine_add_audiodev_property(mc); } DEFINE_MACHINE("fuloong2e", mips_fuloong2e_machine_init) diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index bd397cf2b5c5..3203a4a72898 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -180,8 +180,15 @@ static void pegasos2_init(MachineState *machine) pci_bus_irqs(pci_bus, pegasos2_pci_irq, pm, PCI_NUM_PINS); /* VIA VT8231 South Bridge (multifunction PCI device) */ - via = OBJECT(pci_create_simple_multifunction(pci_bus, PCI_DEVFN(12, 0), - TYPE_VT8231_ISA)); + via = OBJECT(pci_new_multifunction(PCI_DEVFN(12, 0), TYPE_VT8231_ISA)); + + /* Set properties on individual devices before realizing the south bridge */ + if (machine->audiodev) { + dev = PCI_DEVICE(object_resolve_path_component(via, "ac97")); + qdev_prop_set_string(DEVICE(dev), "audiodev", machine->audiodev); + } + + pci_realize_and_unref(PCI_DEVICE(via), pci_bus, &error_abort); for (i = 0; i < PCI_NUM_PINS; i++) { pm->via_pirq[i] = qdev_get_gpio_in_named(DEVICE(via), "pirq", i); } @@ -556,6 +563,7 @@ static void pegasos2_machine_class_init(ObjectClass *oc, void *data) mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("7457_v1.2"); mc->default_ram_id = "pegasos2.ram"; mc->default_ram_size = 512 * MiB; + machine_add_audiodev_property(mc); vhc->cpu_in_nested = pegasos2_cpu_in_nested; vhc->hypercall = pegasos2_hypercall; From cb94ff5f80c537e43c04fa4f071f1df784255310 Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Mon, 2 Oct 2023 16:27:57 +0200 Subject: [PATCH 128/208] audio: propagate Error * out of audio_init Starting from audio_driver_init, propagate errors via Error ** so that audio_init_audiodevs can simply pass &error_fatal, and AUD_register_card can signal faiure. Signed-off-by: Martin Kletzander [Reworked the audio/audio.c parts, while keeping Martin's hw/ changes. - Paolo] Signed-off-by: Paolo Bonzini --- audio/audio.c | 37 ++++++++++++++++++------------------- audio/audio.h | 4 ++-- hw/arm/omap2.c | 2 +- hw/audio/ac97.c | 6 +++++- hw/audio/adlib.c | 6 ++++-- hw/audio/cs4231a.c | 6 ++++-- hw/audio/es1370.c | 5 ++++- hw/audio/gus.c | 6 ++++-- hw/audio/hda-codec.c | 5 ++++- hw/audio/lm4549.c | 8 +++++--- hw/audio/pcspk.c | 4 +--- hw/audio/sb16.c | 6 ++++-- hw/audio/via-ac97.c | 6 ++++-- hw/audio/wm8750.c | 5 ++++- hw/display/xlnx_dp.c | 6 ++++-- hw/input/tsc210x.c | 2 +- hw/usb/dev-audio.c | 5 ++++- softmmu/vl.c | 4 +--- 18 files changed, 74 insertions(+), 49 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 818d79e50f0a..4289b7bf0289 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1556,7 +1556,7 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size) } static int audio_driver_init(AudioState *s, struct audio_driver *drv, - bool msg, Audiodev *dev) + Audiodev *dev, Error **errp) { Error *local_err = NULL; @@ -1577,12 +1577,10 @@ static int audio_driver_init(AudioState *s, struct audio_driver *drv, s->drv = drv; return 0; } else { - if (!msg) { - error_free(local_err); - } else if (local_err) { - error_report_err(local_err); + if (local_err) { + error_propagate(errp, local_err); } else { - error_report("Could not init `%s' audio driver", drv->name); + error_setg(errp, "Could not init `%s' audio driver", drv->name); } return -1; } @@ -1733,7 +1731,7 @@ static void audio_create_default_audiodevs(void) * if dev == NULL => legacy implicit initialization, return the already created * state or create a new one */ -static AudioState *audio_init(Audiodev *dev) +static AudioState *audio_init(Audiodev *dev, Error **errp) { static bool atexit_registered; int done = 0; @@ -1760,9 +1758,9 @@ static AudioState *audio_init(Audiodev *dev) drvname = AudiodevDriver_str(dev->driver); driver = audio_driver_lookup(drvname); if (driver) { - done = !audio_driver_init(s, driver, true, dev); + done = !audio_driver_init(s, driver, dev, errp); } else { - dolog ("Unknown audio driver `%s'\n", drvname); + error_setg(errp, "Unknown audio driver `%s'\n", drvname); } if (!done) { goto out; @@ -1771,13 +1769,13 @@ static AudioState *audio_init(Audiodev *dev) for (;;) { AudiodevListEntry *e = QSIMPLEQ_FIRST(&default_audiodevs); if (!e) { - dolog("no default audio driver available\n"); + error_setg(errp, "no default audio driver available"); goto out; } s->dev = dev = e->dev; drvname = AudiodevDriver_str(dev->driver); driver = audio_driver_lookup(drvname); - if (!audio_driver_init(s, driver, false, dev)) { + if (!audio_driver_init(s, driver, dev, NULL)) { break; } QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next); @@ -1806,7 +1804,7 @@ static AudioState *audio_init(Audiodev *dev) return NULL; } -void AUD_register_card (const char *name, QEMUSoundCard *card) +bool AUD_register_card (const char *name, QEMUSoundCard *card, Error **errp) { if (!card->state) { if (!QTAILQ_EMPTY(&audio_states)) { @@ -1820,13 +1818,18 @@ void AUD_register_card (const char *name, QEMUSoundCard *card) if (QSIMPLEQ_EMPTY(&default_audiodevs)) { audio_create_default_audiodevs(); } - card->state = audio_init(NULL); + card->state = audio_init(NULL, errp); + if (!card->state) { + return false; + } } } card->name = g_strdup (name); memset (&card->entries, 0, sizeof (card->entries)); QLIST_INSERT_HEAD(&card->state->card_head, card, entries); + + return true; } void AUD_remove_card (QEMUSoundCard *card) @@ -2153,17 +2156,13 @@ void audio_define(Audiodev *dev) QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next); } -bool audio_init_audiodevs(void) +void audio_init_audiodevs(void) { AudiodevListEntry *e; QSIMPLEQ_FOREACH(e, &audiodevs, next) { - if (!audio_init(e->dev)) { - return false; - } + audio_init(e->dev, &error_fatal); } - - return true; } audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo) diff --git a/audio/audio.h b/audio/audio.h index 34df8962a669..80f3f92124d5 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -94,7 +94,7 @@ typedef struct QEMUAudioTimeStamp { void AUD_vlog (const char *cap, const char *fmt, va_list ap) G_GNUC_PRINTF(2, 0); void AUD_log (const char *cap, const char *fmt, ...) G_GNUC_PRINTF(2, 3); -void AUD_register_card (const char *name, QEMUSoundCard *card); +bool AUD_register_card (const char *name, QEMUSoundCard *card, Error **errp); void AUD_remove_card (QEMUSoundCard *card); CaptureVoiceOut *AUD_add_capture( AudioState *s, @@ -170,7 +170,7 @@ void audio_sample_from_uint64(void *samples, int pos, void audio_define(Audiodev *audio); void audio_parse_option(const char *opt); -bool audio_init_audiodevs(void); +void audio_init_audiodevs(void); void audio_help(void); AudioState *audio_state_by_name(const char *name, Error **errp); diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c index 41b1f596dcac..f170728e7ece 100644 --- a/hw/arm/omap2.c +++ b/hw/arm/omap2.c @@ -614,7 +614,7 @@ static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta, s->codec.card.name = g_strdup(current_machine->audiodev); s->codec.card.state = audio_state_by_name(s->codec.card.name, &error_fatal); } - AUD_register_card("OMAP EAC", &s->codec.card); + AUD_register_card("OMAP EAC", &s->codec.card, &error_fatal); memory_region_init_io(&s->iomem, NULL, &omap_eac_ops, s, "omap.eac", omap_l4_region_size(ta, 0)); diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index c2a5ce062a1d..6a7a2dc80c4f 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -1273,6 +1273,10 @@ static void ac97_realize(PCIDevice *dev, Error **errp) AC97LinkState *s = AC97(dev); uint8_t *c = s->dev.config; + if (!AUD_register_card ("ac97", &s->card, errp)) { + return; + } + /* TODO: no need to override */ c[PCI_COMMAND] = 0x00; /* pcicmd pci command rw, ro */ c[PCI_COMMAND + 1] = 0x00; @@ -1306,7 +1310,7 @@ static void ac97_realize(PCIDevice *dev, Error **errp) "ac97-nabm", 256); pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nam); pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nabm); - AUD_register_card("ac97", &s->card); + ac97_on_reset(DEVICE(s)); } diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index 5f979b1487d1..bd73806d83af 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -255,6 +255,10 @@ static void adlib_realizefn (DeviceState *dev, Error **errp) AdlibState *s = ADLIB(dev); struct audsettings as; + if (!AUD_register_card ("adlib", &s->card, errp)) { + return; + } + s->opl = OPLCreate (3579545, s->freq); if (!s->opl) { error_setg (errp, "OPLCreate %d failed", s->freq); @@ -270,8 +274,6 @@ static void adlib_realizefn (DeviceState *dev, Error **errp) as.fmt = AUDIO_FORMAT_S16; as.endianness = AUDIO_HOST_ENDIANNESS; - AUD_register_card ("adlib", &s->card); - s->voice = AUD_open_out ( &s->card, s->voice, diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 5c6d64373203..3aa105748d36 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -678,13 +678,15 @@ static void cs4231a_realizefn (DeviceState *dev, Error **errp) return; } + if (!AUD_register_card ("cs4231a", &s->card, errp)) { + return; + } + s->pic = isa_bus_get_irq(bus, s->irq); k = ISADMA_GET_CLASS(s->isa_dma); k->register_channel(s->isa_dma, s->dma, cs_dma_read, s); isa_register_ioport (d, &s->ioports, s->port); - - AUD_register_card ("cs4231a", &s->card); } static Property cs4231a_properties[] = { diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index 4f738a0ad881..90f73d4c23d9 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -853,6 +853,10 @@ static void es1370_realize(PCIDevice *dev, Error **errp) ES1370State *s = ES1370(dev); uint8_t *c = s->dev.config; + if (!AUD_register_card ("es1370", &s->card, errp)) { + return; + } + c[PCI_STATUS + 1] = PCI_STATUS_DEVSEL_SLOW >> 8; #if 0 @@ -868,7 +872,6 @@ static void es1370_realize(PCIDevice *dev, Error **errp) memory_region_init_io (&s->io, OBJECT(s), &es1370_io_ops, s, "es1370", 256); pci_register_bar (&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io); - AUD_register_card ("es1370", &s->card); es1370_reset (s); } diff --git a/hw/audio/gus.c b/hw/audio/gus.c index 787345ce543e..6c2b586ca716 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -241,14 +241,16 @@ static void gus_realizefn (DeviceState *dev, Error **errp) IsaDmaClass *k; struct audsettings as; + if (!AUD_register_card ("gus", &s->card, errp)) { + return; + } + s->isa_dma = isa_bus_get_dma(bus, s->emu.gusdma); if (!s->isa_dma) { error_setg(errp, "ISA controller does not support DMA"); return; } - AUD_register_card ("gus", &s->card); - as.freq = s->freq; as.nchannels = 2; as.fmt = AUDIO_FORMAT_S16; diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c index a26048cf15ed..b9ad1f4c39e7 100644 --- a/hw/audio/hda-codec.c +++ b/hw/audio/hda-codec.c @@ -685,11 +685,14 @@ static void hda_audio_init(HDACodecDevice *hda, const desc_param *param; uint32_t i, type; + if (!AUD_register_card("hda", &a->card, errp)) { + return; + } + a->desc = desc; a->name = object_get_typename(OBJECT(a)); dprint(a, 1, "%s: cad %d\n", __func__, a->hda.cad); - AUD_register_card("hda", &a->card); for (i = 0; i < a->desc->nnodes; i++) { node = a->desc->nodes + i; param = hda_codec_find_param(node, AC_PAR_AUDIO_WIDGET_CAP); diff --git a/hw/audio/lm4549.c b/hw/audio/lm4549.c index 418041bc9c6c..e7bfcc4b9fe8 100644 --- a/hw/audio/lm4549.c +++ b/hw/audio/lm4549.c @@ -281,6 +281,11 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque, { struct audsettings as; + /* Register an audio card */ + if (!AUD_register_card("lm4549", &s->card, errp)) { + return; + } + /* Store the callback and opaque pointer */ s->data_req_cb = data_req_cb; s->opaque = opaque; @@ -288,9 +293,6 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque, /* Init the registers */ lm4549_reset(s); - /* Register an audio card */ - AUD_register_card("lm4549", &s->card); - /* Open a default voice */ as.freq = 48000; as.nchannels = 2; diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index daf92a4ce117..fe7f07ced211 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -123,8 +123,6 @@ static int pcspk_audio_init(PCSpkState *s) return 0; } - AUD_register_card(s_spk, &s->card); - s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as); if (!s->voice) { AUD_log(s_spk, "Could not open voice\n"); @@ -191,7 +189,7 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp) isa_register_ioport(isadev, &s->ioport, s->iobase); - if (s->card.state) { + if (s->card.state && AUD_register_card(s_spk, &s->card, errp)) { pcspk_audio_init(s); } diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index 535ccccdc98e..18f6d252db3a 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -1402,6 +1402,10 @@ static void sb16_realizefn (DeviceState *dev, Error **errp) SB16State *s = SB16 (dev); IsaDmaClass *k; + if (!AUD_register_card ("sb16", &s->card, errp)) { + return; + } + s->isa_hdma = isa_bus_get_dma(bus, s->hdma); s->isa_dma = isa_bus_get_dma(bus, s->dma); if (!s->isa_dma || !s->isa_hdma) { @@ -1434,8 +1438,6 @@ static void sb16_realizefn (DeviceState *dev, Error **errp) k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s); s->can_write = 1; - - AUD_register_card ("sb16", &s->card); } static Property sb16_properties[] = { diff --git a/hw/audio/via-ac97.c b/hw/audio/via-ac97.c index 676254b7a406..30095a4c7aa3 100644 --- a/hw/audio/via-ac97.c +++ b/hw/audio/via-ac97.c @@ -426,6 +426,10 @@ static void via_ac97_realize(PCIDevice *pci_dev, Error **errp) ViaAC97State *s = VIA_AC97(pci_dev); Object *o = OBJECT(s); + if (!AUD_register_card ("via-ac97", &s->card, errp)) { + return; + } + /* * Command register Bus Master bit is documented to be fixed at 0 but it's * needed for PCI DMA to work in QEMU. The pegasos2 firmware writes 0 here @@ -445,8 +449,6 @@ static void via_ac97_realize(PCIDevice *pci_dev, Error **errp) pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->fm); memory_region_init_io(&s->midi, o, &midi_ops, s, "via-ac97.midi", 4); pci_register_bar(pci_dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &s->midi); - - AUD_register_card ("via-ac97", &s->card); } static void via_ac97_exit(PCIDevice *dev) diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c index b5722b37c36b..57954a631442 100644 --- a/hw/audio/wm8750.c +++ b/hw/audio/wm8750.c @@ -624,7 +624,10 @@ static void wm8750_realize(DeviceState *dev, Error **errp) { WM8750State *s = WM8750(dev); - AUD_register_card(CODEC, &s->card); + if (!AUD_register_card(CODEC, &s->card, errp)) { + return; + } + wm8750_reset(I2C_SLAVE(s)); } diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c index 341e91e886fb..eee8f33a5844 100644 --- a/hw/display/xlnx_dp.c +++ b/hw/display/xlnx_dp.c @@ -1302,6 +1302,10 @@ static void xlnx_dp_realize(DeviceState *dev, Error **errp) DisplaySurface *surface; struct audsettings as; + if (!AUD_register_card("xlnx_dp.audio", &s->aud_card, errp)) { + return; + } + aux_bus_realize(s->aux_bus); qdev_realize(DEVICE(s->dpcd), BUS(s->aux_bus), &error_fatal); @@ -1320,8 +1324,6 @@ static void xlnx_dp_realize(DeviceState *dev, Error **errp) as.fmt = AUDIO_FORMAT_S16; as.endianness = 0; - AUD_register_card("xlnx_dp.audio", &s->aud_card); - s->amixer_output_stream = AUD_open_out(&s->aud_card, s->amixer_output_stream, "xlnx_dp.audio.out", diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c index e7960a506960..950506fb3822 100644 --- a/hw/input/tsc210x.c +++ b/hw/input/tsc210x.c @@ -1102,7 +1102,7 @@ static void tsc210x_init(TSC210xState *s, s->card.name = g_strdup(current_machine->audiodev); s->card.state = audio_state_by_name(s->card.name, &error_fatal); } - AUD_register_card(s->name, &s->card); + AUD_register_card(s->name, &s->card, &error_fatal); qemu_register_reset((void *) tsc210x_reset, s); vmstate_register(NULL, 0, vmsd, s); diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 8748c1ba0401..d5ac1f8962e3 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -944,12 +944,15 @@ static void usb_audio_realize(USBDevice *dev, Error **errp) USBAudioState *s = USB_AUDIO(dev); int i; + if (!AUD_register_card(TYPE_USB_AUDIO, &s->card, errp)) { + return; + } + dev->usb_desc = s->multi ? &desc_audio_multi : &desc_audio; usb_desc_create_serial(dev); usb_desc_init(dev); s->dev.opaque = s; - AUD_register_card(TYPE_USB_AUDIO, &s->card); s->out.altset = ALTSET_OFF; s->out.vol.mute = false; diff --git a/softmmu/vl.c b/softmmu/vl.c index cafb1a98427d..98e071e63bb6 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1962,9 +1962,7 @@ static void qemu_create_early_backends(void) * setting machine properties, so they can be referred to. */ configure_blockdev(&bdo_queue, machine_class, snapshot); - if (!audio_init_audiodevs()) { - exit(1); - } + audio_init_audiodevs(); } From 9f8cf356723702272af124e621e4c0e9805c8e22 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 2 Oct 2023 16:48:28 +0200 Subject: [PATCH 129/208] audio: forbid default audiodev backend with -nodefaults Now that all callers support setting an audiodev, forbid using the default audiodev if -nodefaults is provided on the command line. Signed-off-by: Paolo Bonzini --- audio/audio.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/audio/audio.c b/audio/audio.c index 4289b7bf0289..730bf2498dcf 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1692,6 +1692,10 @@ static void audio_create_default_audiodevs(void) { const char *drvname = getenv("QEMU_AUDIO_DRV"); + if (!defaults_enabled()) { + return; + } + /* QEMU_AUDIO_DRV=none is used by libqtest. */ if (drvname && !g_str_equal(drvname, "none")) { error_report("Please use -audiodev instead of QEMU_AUDIO_*"); @@ -1808,6 +1812,14 @@ bool AUD_register_card (const char *name, QEMUSoundCard *card, Error **errp) { if (!card->state) { if (!QTAILQ_EMPTY(&audio_states)) { + /* + * FIXME: once it is possible to create an arbitrary + * default device via -audio DRIVER,OPT=VALUE (no "model"), + * replace this special case with the default AudioState*, + * storing it in a separate global. For now, keep the + * warning to encourage moving off magic use of the first + * -audiodev. + */ if (QSIMPLEQ_EMPTY(&default_audiodevs)) { dolog("Device %s: audiodev default parameter is deprecated, please " "specify audiodev=%s\n", name, @@ -1820,6 +1832,10 @@ bool AUD_register_card (const char *name, QEMUSoundCard *card, Error **errp) } card->state = audio_init(NULL, errp); if (!card->state) { + if (!QSIMPLEQ_EMPTY(&audiodevs)) { + error_append_hint(errp, "Perhaps you wanted to set audiodev=%s?", + QSIMPLEQ_FIRST(&audiodevs)->dev->id); + } return false; } } From 0337e4123e62721bd0bcb4d5645fee2a31e8906d Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 21 Sep 2023 17:29:34 +0900 Subject: [PATCH 130/208] input: Allow to choose console with qemu_input_is_absolute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although an input is routed depending on the console, qemu_input_is_absolute() had no mechanism to specify the console. Accept QemuConsole as an argument for qemu_input_is_absolute, and let the display know the absolute/relative state for a particular console. Signed-off-by: Akihiko Odaki Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Marc-André Lureau Message-Id: <20230921082936.28100-1-akihiko.odaki@daynix.com> --- include/ui/input.h | 2 +- ui/cocoa.m | 2 +- ui/dbus-console.c | 6 +++--- ui/gtk.c | 12 ++++++------ ui/input.c | 29 +++++++---------------------- ui/sdl2.c | 26 +++++++++++++------------- ui/spice-input.c | 2 +- ui/trace-events | 1 - ui/vnc.c | 2 +- 9 files changed, 33 insertions(+), 49 deletions(-) diff --git a/include/ui/input.h b/include/ui/input.h index c29a730a71be..24d8e4579e42 100644 --- a/include/ui/input.h +++ b/include/ui/input.h @@ -57,7 +57,7 @@ void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down); void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map, uint32_t button_old, uint32_t button_new); -bool qemu_input_is_absolute(void); +bool qemu_input_is_absolute(QemuConsole *con); int qemu_input_scale_axis(int value, int min_in, int max_in, int min_out, int max_out); diff --git a/ui/cocoa.m b/ui/cocoa.m index df6d13be38e7..145f42d19054 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -2001,7 +2001,7 @@ static void cocoa_refresh(DisplayChangeListener *dcl) COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n"); graphic_hw_update(NULL); - if (qemu_input_is_absolute()) { + if (qemu_input_is_absolute(dcl->con)) { dispatch_async(dispatch_get_main_queue(), ^{ if (![cocoaView isAbsoluteEnabled]) { if ([cocoaView isMouseGrabbed]) { diff --git a/ui/dbus-console.c b/ui/dbus-console.c index 36f7349585c5..49da9ccc83c3 100644 --- a/ui/dbus-console.c +++ b/ui/dbus-console.c @@ -386,7 +386,7 @@ dbus_mouse_rel_motion(DBusDisplayConsole *ddc, { trace_dbus_mouse_rel_motion(dx, dy); - if (qemu_input_is_absolute()) { + if (qemu_input_is_absolute(ddc->dcl.con)) { g_dbus_method_invocation_return_error( invocation, DBUS_DISPLAY_ERROR, DBUS_DISPLAY_ERROR_INVALID, @@ -453,7 +453,7 @@ dbus_mouse_set_pos(DBusDisplayConsole *ddc, trace_dbus_mouse_set_pos(x, y); - if (!qemu_input_is_absolute()) { + if (!qemu_input_is_absolute(ddc->dcl.con)) { g_dbus_method_invocation_return_error( invocation, DBUS_DISPLAY_ERROR, DBUS_DISPLAY_ERROR_INVALID, @@ -514,7 +514,7 @@ static void dbus_mouse_update_is_absolute(DBusDisplayConsole *ddc) { g_object_set(ddc->iface_mouse, - "is-absolute", qemu_input_is_absolute(), + "is-absolute", qemu_input_is_absolute(ddc->dcl.con), NULL); } diff --git a/ui/gtk.c b/ui/gtk.c index 3373427c9b89..cd3b8953cd7f 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -204,7 +204,7 @@ static void gd_update_cursor(VirtualConsole *vc) } window = gtk_widget_get_window(GTK_WIDGET(vc->gfx.drawing_area)); - if (s->full_screen || qemu_input_is_absolute() || s->ptr_owner == vc) { + if (s->full_screen || qemu_input_is_absolute(vc->gfx.dcl.con) || s->ptr_owner == vc) { gdk_window_set_cursor(window, s->null_cursor); } else { gdk_window_set_cursor(window, NULL); @@ -453,7 +453,7 @@ static void gd_mouse_set(DisplayChangeListener *dcl, gint x_root, y_root; if (!gtk_widget_get_realized(vc->gfx.drawing_area) || - qemu_input_is_absolute()) { + qemu_input_is_absolute(dcl->con)) { return; } @@ -689,7 +689,7 @@ static void gd_mouse_mode_change(Notifier *notify, void *data) s = container_of(notify, GtkDisplayState, mouse_mode_notifier); /* release the grab at switching to absolute mode */ - if (qemu_input_is_absolute() && s->ptr_owner) { + if (s->ptr_owner && qemu_input_is_absolute(s->ptr_owner->gfx.dcl.con)) { if (!s->ptr_owner->window) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), FALSE); @@ -903,7 +903,7 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, x = (motion->x - mx) / vc->gfx.scale_x * ws; y = (motion->y - my) / vc->gfx.scale_y * ws; - if (qemu_input_is_absolute()) { + if (qemu_input_is_absolute(vc->gfx.dcl.con)) { if (x < 0 || y < 0 || x >= surface_width(vc->gfx.ds) || y >= surface_height(vc->gfx.ds)) { @@ -923,7 +923,7 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, s->last_y = y; s->last_set = TRUE; - if (!qemu_input_is_absolute() && s->ptr_owner == vc) { + if (!qemu_input_is_absolute(vc->gfx.dcl.con) && s->ptr_owner == vc) { GdkScreen *screen = gtk_widget_get_screen(vc->gfx.drawing_area); GdkDisplay *dpy = gtk_widget_get_display(widget); GdkWindow *win = gtk_widget_get_window(widget); @@ -965,7 +965,7 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button, /* implicitly grab the input at the first click in the relative mode */ if (button->button == 1 && button->type == GDK_BUTTON_PRESS && - !qemu_input_is_absolute() && s->ptr_owner != vc) { + !qemu_input_is_absolute(vc->gfx.dcl.con) && s->ptr_owner != vc) { if (!vc->window) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), TRUE); diff --git a/ui/input.c b/ui/input.c index 1aad64b07c41..cbe8573c5ce7 100644 --- a/ui/input.c +++ b/ui/input.c @@ -56,7 +56,7 @@ QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev, s->id = id++; QTAILQ_INSERT_TAIL(&handlers, s, node); - qemu_input_check_mode_change(); + notifier_list_notify(&mouse_mode_notifiers, NULL); return s; } @@ -64,21 +64,21 @@ void qemu_input_handler_activate(QemuInputHandlerState *s) { QTAILQ_REMOVE(&handlers, s, node); QTAILQ_INSERT_HEAD(&handlers, s, node); - qemu_input_check_mode_change(); + notifier_list_notify(&mouse_mode_notifiers, NULL); } void qemu_input_handler_deactivate(QemuInputHandlerState *s) { QTAILQ_REMOVE(&handlers, s, node); QTAILQ_INSERT_TAIL(&handlers, s, node); - qemu_input_check_mode_change(); + notifier_list_notify(&mouse_mode_notifiers, NULL); } void qemu_input_handler_unregister(QemuInputHandlerState *s) { QTAILQ_REMOVE(&handlers, s, node); g_free(s); - qemu_input_check_mode_change(); + notifier_list_notify(&mouse_mode_notifiers, NULL); } void qemu_input_handler_bind(QemuInputHandlerState *s, @@ -494,12 +494,12 @@ void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map, } } -bool qemu_input_is_absolute(void) +bool qemu_input_is_absolute(QemuConsole *con) { QemuInputHandlerState *s; s = qemu_input_find_handler(INPUT_EVENT_MASK_REL | INPUT_EVENT_MASK_ABS, - NULL); + con); return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS); } @@ -583,21 +583,6 @@ void qemu_input_queue_mtt_abs(QemuConsole *src, InputAxis axis, int value, qemu_input_event_send(src, &evt); } -void qemu_input_check_mode_change(void) -{ - static int current_is_absolute; - int is_absolute; - - is_absolute = qemu_input_is_absolute(); - - if (is_absolute != current_is_absolute) { - trace_input_mouse_mode(is_absolute); - notifier_list_notify(&mouse_mode_notifiers, NULL); - } - - current_is_absolute = is_absolute; -} - void qemu_add_mouse_mode_change_notifier(Notifier *notify) { notifier_list_add(&mouse_mode_notifiers, notify); @@ -657,6 +642,6 @@ bool qemu_mouse_set(int index, Error **errp) } qemu_input_handler_activate(s); - qemu_input_check_mode_change(); + notifier_list_notify(&mouse_mode_notifiers, NULL); return true; } diff --git a/ui/sdl2.c b/ui/sdl2.c index 178cc054abf1..fbfdb64e909c 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -203,7 +203,7 @@ static void sdl_hide_cursor(struct sdl2_console *scon) SDL_ShowCursor(SDL_DISABLE); SDL_SetCursor(sdl_cursor_hidden); - if (!qemu_input_is_absolute()) { + if (!qemu_input_is_absolute(scon->dcl.con)) { SDL_SetRelativeMouseMode(SDL_TRUE); } } @@ -214,12 +214,12 @@ static void sdl_show_cursor(struct sdl2_console *scon) return; } - if (!qemu_input_is_absolute()) { + if (!qemu_input_is_absolute(scon->dcl.con)) { SDL_SetRelativeMouseMode(SDL_FALSE); } if (guest_cursor && - (gui_grab || qemu_input_is_absolute() || absolute_enabled)) { + (gui_grab || qemu_input_is_absolute(scon->dcl.con) || absolute_enabled)) { SDL_SetCursor(guest_sprite); } else { SDL_SetCursor(sdl_cursor_normal); @@ -245,7 +245,7 @@ static void sdl_grab_start(struct sdl2_console *scon) } if (guest_cursor) { SDL_SetCursor(guest_sprite); - if (!qemu_input_is_absolute() && !absolute_enabled) { + if (!qemu_input_is_absolute(scon->dcl.con) && !absolute_enabled) { SDL_WarpMouseInWindow(scon->real_window, guest_x, guest_y); } } else { @@ -280,7 +280,7 @@ static void absolute_mouse_grab(struct sdl2_console *scon) static void sdl_mouse_mode_change(Notifier *notify, void *data) { - if (qemu_input_is_absolute()) { + if (qemu_input_is_absolute(sdl2_console[0].dcl.con)) { if (!absolute_enabled) { absolute_enabled = 1; SDL_SetRelativeMouseMode(SDL_FALSE); @@ -311,7 +311,7 @@ static void sdl_send_mouse_event(struct sdl2_console *scon, int dx, int dy, prev_state = state; } - if (qemu_input_is_absolute()) { + if (qemu_input_is_absolute(scon->dcl.con)) { qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_X, x, 0, surface_width(scon->surface)); qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_Y, @@ -497,7 +497,7 @@ static void handle_mousemotion(SDL_Event *ev) return; } - if (qemu_input_is_absolute() || absolute_enabled) { + if (qemu_input_is_absolute(scon->dcl.con) || absolute_enabled) { int scr_w, scr_h; SDL_GetWindowSize(scon->real_window, &scr_w, &scr_h); max_x = scr_w - 1; @@ -513,7 +513,7 @@ static void handle_mousemotion(SDL_Event *ev) sdl_grab_start(scon); } } - if (gui_grab || qemu_input_is_absolute() || absolute_enabled) { + if (gui_grab || qemu_input_is_absolute(scon->dcl.con) || absolute_enabled) { sdl_send_mouse_event(scon, ev->motion.xrel, ev->motion.yrel, ev->motion.x, ev->motion.y, ev->motion.state); } @@ -530,7 +530,7 @@ static void handle_mousebutton(SDL_Event *ev) } bev = &ev->button; - if (!gui_grab && !qemu_input_is_absolute()) { + if (!gui_grab && !qemu_input_is_absolute(scon->dcl.con)) { if (ev->type == SDL_MOUSEBUTTONUP && bev->button == SDL_BUTTON_LEFT) { /* start grabbing all events */ sdl_grab_start(scon); @@ -603,7 +603,7 @@ static void handle_windowevent(SDL_Event *ev) } /* fall through */ case SDL_WINDOWEVENT_ENTER: - if (!gui_grab && (qemu_input_is_absolute() || absolute_enabled)) { + if (!gui_grab && (qemu_input_is_absolute(scon->dcl.con) || absolute_enabled)) { absolute_mouse_grab(scon); } /* If a new console window opened using a hotkey receives the @@ -733,9 +733,9 @@ static void sdl_mouse_warp(DisplayChangeListener *dcl, if (!guest_cursor) { sdl_show_cursor(scon); } - if (gui_grab || qemu_input_is_absolute() || absolute_enabled) { + if (gui_grab || qemu_input_is_absolute(scon->dcl.con) || absolute_enabled) { SDL_SetCursor(guest_sprite); - if (!qemu_input_is_absolute() && !absolute_enabled) { + if (!qemu_input_is_absolute(scon->dcl.con) && !absolute_enabled) { SDL_WarpMouseInWindow(scon->real_window, x, y); } } @@ -773,7 +773,7 @@ static void sdl_mouse_define(DisplayChangeListener *dcl, return; } if (guest_cursor && - (gui_grab || qemu_input_is_absolute() || absolute_enabled)) { + (gui_grab || qemu_input_is_absolute(dcl->con) || absolute_enabled)) { SDL_SetCursor(guest_sprite); } } diff --git a/ui/spice-input.c b/ui/spice-input.c index bbd502564edf..a5c5d78474e7 100644 --- a/ui/spice-input.c +++ b/ui/spice-input.c @@ -224,7 +224,7 @@ static const SpiceTabletInterface tablet_interface = { static void mouse_mode_notifier(Notifier *notifier, void *data) { QemuSpicePointer *pointer = container_of(notifier, QemuSpicePointer, mouse_mode); - bool is_absolute = qemu_input_is_absolute(); + bool is_absolute = qemu_input_is_absolute(NULL); if (pointer->absolute == is_absolute) { return; diff --git a/ui/trace-events b/ui/trace-events index 76b19a299588..16c35c9fd6f0 100644 --- a/ui/trace-events +++ b/ui/trace-events @@ -92,7 +92,6 @@ input_event_rel(int conidx, const char *axis, int value) "con %d, axis %s, value input_event_abs(int conidx, const char *axis, int value) "con %d, axis %s, value 0x%x" input_event_mtt(int conidx, const char *axis, int value) "con %d, axis %s, value 0x%x" input_event_sync(void) "" -input_mouse_mode(int absolute) "absolute %d" # sdl2-input.c sdl2_process_key(int sdl_scancode, int qcode, const char *action) "translated SDL scancode %d to QKeyCode %d (%s)" diff --git a/ui/vnc.c b/ui/vnc.c index 523eb1f5b0ac..c66477a3902d 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1771,7 +1771,7 @@ uint32_t read_u32(uint8_t *data, size_t offset) static void check_pointer_type_change(Notifier *notifier, void *data) { VncState *vs = container_of(notifier, VncState, mouse_mode_notifier); - int absolute = qemu_input_is_absolute(); + int absolute = qemu_input_is_absolute(vs->vd->dcl.con); if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE) && vs->absolute != absolute) { vnc_lock_output(vs); From 845fff1f83ac87f592b5b0fa01c37844ea8cc9f9 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Wed, 13 Sep 2023 16:49:56 +0200 Subject: [PATCH 131/208] ui/console: make qemu_console_is_multihead() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qemu_console_is_multihead() is only called from within "ui/console.c"; make it static. Cc: "Marc-André Lureau" (odd fixer:Graphics) Cc: Gerd Hoffmann (odd fixer:Graphics) Signed-off-by: Laszlo Ersek Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Marc-André Lureau Message-ID: <20230913144959.41891-2-lersek@redhat.com> --- include/ui/console.h | 1 - ui/console.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 28882f15a531..acb61a7f1523 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -422,7 +422,6 @@ bool qemu_console_is_visible(QemuConsole *con); bool qemu_console_is_graphic(QemuConsole *con); bool qemu_console_is_fixedsize(QemuConsole *con); bool qemu_console_is_gl_blocked(QemuConsole *con); -bool qemu_console_is_multihead(DeviceState *dev); char *qemu_console_get_label(QemuConsole *con); int qemu_console_get_index(QemuConsole *con); uint32_t qemu_console_get_head(QemuConsole *con); diff --git a/ui/console.c b/ui/console.c index 4a4f19ed33e6..d17b4ee397e7 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1434,7 +1434,7 @@ bool qemu_console_is_gl_blocked(QemuConsole *con) return con->gl_block; } -bool qemu_console_is_multihead(DeviceState *dev) +static bool qemu_console_is_multihead(DeviceState *dev) { QemuConsole *con; Object *obj; From 4ce2f97c000629531553328e1871b56312a210cf Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Wed, 13 Sep 2023 16:49:57 +0200 Subject: [PATCH 132/208] ui/console: only walk QemuGraphicConsoles in qemu_console_is_multihead() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qemu_console_is_multihead() declares the console "c" a "multihead" console if there are two different consoles in the system that (a) both reference "c->device", and (b) have different "c->head" numbers. In effect, if at least two consoles exist that are different heads of the same device that underlies "c". Commit 58d5870845c6 ("ui/console: move graphic fields to QemuGraphicConsole", 2023-09-04) pushed the "device" and "head" members from the QemuConsole base class down to the QemuGraphicConsole subclass, adjusting the referring QOM properties accordingly as well. As a result, the "device" property lookup in qemu_console_is_multihead() now crashes, in case the candidate console being investigated for criterion (a) is not a QemuGraphicConsole instance: > Unexpected error in object_property_find_err() at qom/object.c:1314: > qemu: Property 'qemu-fixed-text-console.device' not found > Aborted (core dumped) This is effectively an unchecked downcast. Make it checked: only consider such console candidates that are themselves QemuGraphicConsole instances. Cc: "Marc-André Lureau" (odd fixer:Graphics) Cc: Gerd Hoffmann (odd fixer:Graphics) Fixes: 58d5870845c6 Signed-off-by: Laszlo Ersek Reviewed-by: Marc-André Lureau Message-ID: <20230913144959.41891-3-lersek@redhat.com> --- ui/console.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/console.c b/ui/console.c index d17b4ee397e7..4fe26c08fbaa 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1442,6 +1442,9 @@ static bool qemu_console_is_multihead(DeviceState *dev) uint32_t h; QTAILQ_FOREACH(con, &consoles, next) { + if (!QEMU_IS_GRAPHIC_CONSOLE(con)) { + continue; + } obj = object_property_get_link(OBJECT(con), "device", &error_abort); if (DEVICE(obj) != dev) { From 2c0c4c1f650d48c814df5a8b48544ea44918bd8f Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Wed, 13 Sep 2023 16:49:58 +0200 Subject: [PATCH 133/208] ui/console: eliminate QOM properties from qemu_console_is_multihead() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to Marc-André's and Gerd's descriptions, the "device" and "head" members of QemuGraphicConsole are exposed as QOM properties for two purposes: (1) Introspection (e.g., "qom-get" monitor command). (2) A VNC server can display a specific device + head. This lets us run a multihead configuration by using multiple VNC servers (one for each head). Further, we can link input devices to device + head, so input events are routed to different devices dependent on where they are coming from. Which is most useful for tablet devices in a VNC multihead setup, each head has its own tablet device then. This does requires manual guest-side configuration, for establishing the same tablet <-> head relationship. However, neither goal seems to justify the complicated QOM property lookup that's internal to qemu_console_is_multihead(). Rework qemu_console_is_multihead() with plain old C language field accesses. Cc: "Marc-André Lureau" (odd fixer:Graphics) Cc: Gerd Hoffmann (odd fixer:Graphics) Signed-off-by: Laszlo Ersek Reviewed-by: Marc-André Lureau Message-ID: <20230913144959.41891-4-lersek@redhat.com> --- ui/console.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ui/console.c b/ui/console.c index 4fe26c08fbaa..65463d84a7a2 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1434,25 +1434,25 @@ bool qemu_console_is_gl_blocked(QemuConsole *con) return con->gl_block; } -static bool qemu_console_is_multihead(DeviceState *dev) +static bool qemu_graphic_console_is_multihead(QemuGraphicConsole *c) { QemuConsole *con; - Object *obj; uint32_t f = 0xffffffff; uint32_t h; QTAILQ_FOREACH(con, &consoles, next) { + QemuGraphicConsole *candidate; + if (!QEMU_IS_GRAPHIC_CONSOLE(con)) { continue; } - obj = object_property_get_link(OBJECT(con), - "device", &error_abort); - if (DEVICE(obj) != dev) { + + candidate = QEMU_GRAPHIC_CONSOLE(con); + if (candidate->device != c->device) { continue; } - h = object_property_get_uint(OBJECT(con), - "head", &error_abort); + h = candidate->head; if (f == 0xffffffff) { f = h; } else if (h != f) { @@ -1471,7 +1471,7 @@ char *qemu_console_get_label(QemuConsole *con) bool multihead; dev = DEVICE(c->device); - multihead = qemu_console_is_multihead(dev); + multihead = qemu_graphic_console_is_multihead(c); if (multihead) { return g_strdup_printf("%s.%d", dev->id ? dev->id : From 65d7ceb49b434d578cee61467c009cb16a794b16 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Wed, 13 Sep 2023 16:49:59 +0200 Subject: [PATCH 134/208] ui/console: sanitize search in qemu_graphic_console_is_multihead() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qemu_graphic_console_is_multihead() declares the graphical console "c" a "multihead" console if there are two different graphical consoles in the system that (a) both reference "c->device", and (b) have different "c->head" numbers. In effect, if at least two graphical consoles exist that are different heads of the same device that underlies "c". In fact, "c" may be one of these two graphical consoles, or "c" may differ from both of those consoles (in case "c->device" has at least three heads). The loop currently uses this awkward "two different consoles" approach because the function used not to have access to "c", only to "c->device", which didn't allow for fetching (and comparing) "c->head". But, we've changed that in the last patch; we now pass all of "c" to qemu_graphic_console_is_multihead(). Thus, look for the *first* (and possibly *only*) graphical console, if any, that refers to the same "device" as "c", but by a different "head" number. Cc: "Marc-André Lureau" (odd fixer:Graphics) Cc: Gerd Hoffmann (odd fixer:Graphics) Signed-off-by: Laszlo Ersek Reviewed-by: Marc-André Lureau Message-ID: <20230913144959.41891-5-lersek@redhat.com> --- ui/console.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ui/console.c b/ui/console.c index 65463d84a7a2..8ee66d10c57c 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1437,8 +1437,6 @@ bool qemu_console_is_gl_blocked(QemuConsole *con) static bool qemu_graphic_console_is_multihead(QemuGraphicConsole *c) { QemuConsole *con; - uint32_t f = 0xffffffff; - uint32_t h; QTAILQ_FOREACH(con, &consoles, next) { QemuGraphicConsole *candidate; @@ -1452,10 +1450,7 @@ static bool qemu_graphic_console_is_multihead(QemuGraphicConsole *c) continue; } - h = candidate->head; - if (f == 0xffffffff) { - f = h; - } else if (h != f) { + if (candidate->head != c->head) { return true; } } From 7db57a73f66463488fbd53fe5f9589de49534fe8 Mon Sep 17 00:00:00 2001 From: Ken Xue Date: Thu, 14 Sep 2023 09:31:51 +0800 Subject: [PATCH 135/208] ui: add XBGR8888 and ABGR8888 in drm_format_pixman_map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Android uses XBGR8888 and ABGR8888 as default scanout buffer, But qemu does not support them for qemu_pixman_to_drm_format conversion within virtio_gpu_create_dmabuf for virtio gpu. so, add those 2 formats into drm_format_pixman_map. Signed-off-by: Ken Xue Reviewed-by: Marc-André Lureau Message-ID: <20230914013151.805363-1-Ken.Xue@amd.com> --- include/ui/qemu-pixman.h | 4 ++++ ui/qemu-pixman.c | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h index 51f870932791..e587c48b1fde 100644 --- a/include/ui/qemu-pixman.h +++ b/include/ui/qemu-pixman.h @@ -32,6 +32,8 @@ # define PIXMAN_LE_r8g8b8 PIXMAN_b8g8r8 # define PIXMAN_LE_a8r8g8b8 PIXMAN_b8g8r8a8 # define PIXMAN_LE_x8r8g8b8 PIXMAN_b8g8r8x8 +# define PIXMAN_LE_a8b8g8r8 PIXMAN_r8g8b8a8 +# define PIXMAN_LE_x8b8g8r8 PIXMAN_r8g8b8x8 #else # define PIXMAN_BE_r8g8b8 PIXMAN_b8g8r8 # define PIXMAN_BE_x8r8g8b8 PIXMAN_b8g8r8x8 @@ -45,6 +47,8 @@ # define PIXMAN_LE_r8g8b8 PIXMAN_r8g8b8 # define PIXMAN_LE_a8r8g8b8 PIXMAN_a8r8g8b8 # define PIXMAN_LE_x8r8g8b8 PIXMAN_x8r8g8b8 +# define PIXMAN_LE_a8b8g8r8 PIXMAN_a8b8g8r8 +# define PIXMAN_LE_x8b8g8r8 PIXMAN_x8b8g8r8 #endif #define QEMU_PIXMAN_COLOR(r, g, b) \ diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c index be00a96340d3..b43ec38bf0e9 100644 --- a/ui/qemu-pixman.c +++ b/ui/qemu-pixman.c @@ -96,7 +96,9 @@ static const struct { } drm_format_pixman_map[] = { { DRM_FORMAT_RGB888, PIXMAN_LE_r8g8b8 }, { DRM_FORMAT_ARGB8888, PIXMAN_LE_a8r8g8b8 }, - { DRM_FORMAT_XRGB8888, PIXMAN_LE_x8r8g8b8 } + { DRM_FORMAT_XRGB8888, PIXMAN_LE_x8r8g8b8 }, + { DRM_FORMAT_XBGR8888, PIXMAN_LE_x8b8g8r8 }, + { DRM_FORMAT_ABGR8888, PIXMAN_LE_a8b8g8r8 }, }; pixman_format_code_t qemu_drm_format_to_pixman(uint32_t drm_format) From 75b773d84c89220463a14a6883d2b2a8e49e5b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 25 Sep 2023 15:36:04 +0400 Subject: [PATCH 136/208] win32: avoid discarding the exception handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In all likelihood, the compiler with lto doesn't see the function being used, from assembly macro __try1. Help it by marking the function has being used. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1904 Fixes: commit d89f30b4df ("win32: wrap socket close() with an exception handler") Signed-off-by: Marc-André Lureau Reviewed-by: Thomas Huth --- include/qemu/compiler.h | 6 ++++++ util/oslib-win32.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h index 7f1bbbf05f4f..1109482a000c 100644 --- a/include/qemu/compiler.h +++ b/include/qemu/compiler.h @@ -206,4 +206,10 @@ #define QEMU_ANNOTATE(x) #endif +#if __has_attribute(used) +# define QEMU_USED __attribute__((used)) +#else +# define QEMU_USED +#endif + #endif /* COMPILER_H */ diff --git a/util/oslib-win32.c b/util/oslib-win32.c index 19a0ea7fbe66..55b0189dc304 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -479,7 +479,7 @@ int qemu_bind_wrap(int sockfd, const struct sockaddr *addr, return ret; } -EXCEPTION_DISPOSITION +QEMU_USED EXCEPTION_DISPOSITION win32_close_exception_handler(struct _EXCEPTION_RECORD *exception_record, void *registration, struct _CONTEXT *context, void *dispatcher) From 9bd4d3df633593878ada3dffcfe05318754b4596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 15 Sep 2023 15:28:31 +0400 Subject: [PATCH 137/208] ui/gtk: fix UI info precondition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dpy_get_ui_info() shouldn't be called if the underlying GPU doesn't support it. Before the assert() was added and the regression introduced, GTK code used to get "zero" UI info, for ex with a simple VGA device. The assert was added to prevent from calling when there are no console too. The other display backend that calls dpy_get_ui_info() correctly checks that pre-condition. Calling dpy_set_ui_info() is "safe" in this case, it will simply return an error that can be generally ignored. Fixes: commit a92e7bb4c ("ui: add precondition for dpy_get_ui_info()") Signed-off-by: Marc-André Lureau --- ui/gtk.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ui/gtk.c b/ui/gtk.c index cd3b8953cd7f..935de1209b17 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -726,6 +726,10 @@ static void gd_set_ui_refresh_rate(VirtualConsole *vc, int refresh_rate) { QemuUIInfo info; + if (!dpy_ui_info_supported(vc->gfx.dcl.con)) { + return; + } + info = *dpy_get_ui_info(vc->gfx.dcl.con); info.refresh_rate = refresh_rate; dpy_set_ui_info(vc->gfx.dcl.con, &info, true); @@ -735,6 +739,10 @@ static void gd_set_ui_size(VirtualConsole *vc, gint width, gint height) { QemuUIInfo info; + if (!dpy_ui_info_supported(vc->gfx.dcl.con)) { + return; + } + info = *dpy_get_ui_info(vc->gfx.dcl.con); info.width = width; info.height = height; From f1de309792d6656ef3443ba65272c4a868a43914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 20 Sep 2023 11:54:54 +0400 Subject: [PATCH 138/208] analyze-migration: ignore RAM_SAVE_FLAG_MULTIFD_FLUSH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Traceback (most recent call last): File "scripts/analyze-migration.py", line 605, in dump.read(dump_memory = args.memory) File "scripts/analyze-migration.py", line 542, in read section.read() File "scripts/analyze-migration.py", line 214, in read raise Exception("Unknown RAM flags: %x" % flags) Exception: Unknown RAM flags: 200 See commit 77c259a4cb ("multifd: Create property multifd-flush-after-each-section") Signed-off-by: Marc-André Lureau Reviewed-by: Fabiano Rosas --- scripts/analyze-migration.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/analyze-migration.py b/scripts/analyze-migration.py index b82a1b0c58c4..082424558b2a 100755 --- a/scripts/analyze-migration.py +++ b/scripts/analyze-migration.py @@ -111,6 +111,8 @@ class RamSection(object): RAM_SAVE_FLAG_CONTINUE = 0x20 RAM_SAVE_FLAG_XBZRLE = 0x40 RAM_SAVE_FLAG_HOOK = 0x80 + RAM_SAVE_FLAG_COMPRESS_PAGE = 0x100 + RAM_SAVE_FLAG_MULTIFD_FLUSH = 0x200 def __init__(self, file, version_id, ramargs, section_key): if version_id != 4: @@ -205,6 +207,8 @@ def read(self): raise Exception("XBZRLE RAM compression is not supported yet") elif flags & self.RAM_SAVE_FLAG_HOOK: raise Exception("RAM hooks don't make sense with files") + if flags & self.RAM_SAVE_FLAG_MULTIFD_FLUSH: + continue # End of RAM section if flags & self.RAM_SAVE_FLAG_EOS: From 314e0a84cd5d3a8d04c9778eecb5618dee3574cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 2 Oct 2023 14:27:36 +0400 Subject: [PATCH 139/208] hw/core: remove needless includes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The include list is large, make it smaller. Signed-off-by: Marc-André Lureau Acked-by: Laszlo Ersek --- hw/core/machine.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index a232ae0bcdbd..df40f10dfae9 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -11,32 +11,22 @@ */ #include "qemu/osdep.h" -#include "qemu/option.h" #include "qemu/accel.h" #include "sysemu/replay.h" -#include "qemu/units.h" #include "hw/boards.h" #include "hw/loader.h" #include "qapi/error.h" -#include "qapi/qapi-visit-common.h" #include "qapi/qapi-visit-machine.h" -#include "qapi/visitor.h" #include "qom/object_interfaces.h" -#include "hw/sysbus.h" #include "sysemu/cpus.h" #include "sysemu/sysemu.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" -#include "sysemu/numa.h" #include "sysemu/xen.h" -#include "qemu/error-report.h" #include "sysemu/qtest.h" -#include "hw/pci/pci.h" #include "hw/mem/nvdimm.h" #include "migration/global_state.h" -#include "migration/vmstate.h" #include "exec/confidential-guest-support.h" -#include "hw/virtio/virtio.h" #include "hw/virtio/virtio-pci.h" #include "hw/virtio/virtio-net.h" From bf7e5215c40c9c38067798fdced94623f2ee0201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 2 Oct 2023 14:27:36 +0400 Subject: [PATCH 140/208] hw/pc: remove needless includes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The include list is gigantic, make it smaller. Signed-off-by: Marc-André Lureau Acked-by: Laszlo Ersek --- hw/i386/pc.c | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 5d399b6247ea..ec01d74482da 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -24,79 +24,40 @@ #include "qemu/osdep.h" #include "qemu/units.h" -#include "hw/i386/x86.h" #include "hw/i386/pc.h" #include "hw/char/serial.h" #include "hw/char/parallel.h" -#include "hw/i386/topology.h" #include "hw/i386/fw_cfg.h" #include "hw/i386/vmport.h" #include "sysemu/cpus.h" -#include "hw/block/fdc.h" #include "hw/ide/internal.h" -#include "hw/ide/isa.h" -#include "hw/pci/pci.h" -#include "hw/pci/pci_bus.h" -#include "hw/pci-bridge/pci_expander_bridge.h" -#include "hw/nvram/fw_cfg.h" #include "hw/timer/hpet.h" -#include "hw/firmware/smbios.h" #include "hw/loader.h" -#include "elf.h" -#include "migration/vmstate.h" -#include "multiboot.h" #include "hw/rtc/mc146818rtc.h" #include "hw/intc/i8259.h" -#include "hw/intc/ioapic.h" #include "hw/timer/i8254.h" #include "hw/input/i8042.h" -#include "hw/irq.h" #include "hw/audio/pcspk.h" -#include "hw/pci/msi.h" -#include "hw/sysbus.h" #include "sysemu/sysemu.h" -#include "sysemu/tcg.h" -#include "sysemu/numa.h" -#include "sysemu/kvm.h" #include "sysemu/xen.h" #include "sysemu/reset.h" -#include "sysemu/runstate.h" #include "kvm/kvm_i386.h" #include "hw/xen/xen.h" -#include "hw/xen/start_info.h" -#include "ui/qemu-spice.h" -#include "exec/memory.h" -#include "qemu/bitmap.h" -#include "qemu/config-file.h" #include "qemu/error-report.h" -#include "qemu/option.h" -#include "qemu/cutils.h" -#include "hw/acpi/acpi.h" #include "hw/acpi/cpu_hotplug.h" #include "acpi-build.h" -#include "hw/mem/pc-dimm.h" #include "hw/mem/nvdimm.h" -#include "hw/cxl/cxl.h" #include "hw/cxl/cxl_host.h" -#include "qapi/error.h" -#include "qapi/qapi-visit-common.h" -#include "qapi/qapi-visit-machine.h" -#include "qapi/visitor.h" -#include "hw/core/cpu.h" #include "hw/usb.h" #include "hw/i386/intel_iommu.h" #include "hw/net/ne2000-isa.h" -#include "standard-headers/asm-x86/bootparam.h" #include "hw/virtio/virtio-iommu.h" #include "hw/virtio/virtio-md-pci.h" #include "hw/i386/kvm/xen_overlay.h" #include "hw/i386/kvm/xen_evtchn.h" #include "hw/i386/kvm/xen_gnttab.h" #include "hw/i386/kvm/xen_xenstore.h" -#include "sysemu/replay.h" -#include "target/i386/cpu.h" #include "e820_memory_layout.h" -#include "fw_cfg.h" #include "trace.h" #include CONFIG_DEVICES From e0288a778473ebd35eac6cc1924faca7d477d241 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Tue, 19 Sep 2023 15:19:55 +0200 Subject: [PATCH 141/208] hw/display/ramfb: plug slight guest-triggerable leak on mode setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fw_cfg DMA write callback in ramfb prepares a new display surface in QEMU; this new surface is put to use ("swapped in") upon the next display update. At that time, the old surface (if any) is released. If the guest triggers the fw_cfg DMA write callback at least twice between two adjacent display updates, then the second callback (and further such callbacks) will leak the previously prepared (but not yet swapped in) display surface. The issue can be shown by: (1) starting QEMU with "-trace displaysurface_free", and (2) running the following program in the guest UEFI shell: > #include // ShellAppMain() > #include // gBS > #include // EFI_GRAPHICS_OUTPUT_PROTOCOL > > INTN > EFIAPI > ShellAppMain ( > IN UINTN Argc, > IN CHAR16 **Argv > ) > { > EFI_STATUS Status; > VOID *Interface; > EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; > UINT32 Mode; > > Status = gBS->LocateProtocol ( > &gEfiGraphicsOutputProtocolGuid, > NULL, > &Interface > ); > if (EFI_ERROR (Status)) { > return 1; > } > > Gop = Interface; > > Mode = 1; > for ( ; ;) { > Status = Gop->SetMode (Gop, Mode); > if (EFI_ERROR (Status)) { > break; > } > > Mode = 1 - Mode; > } > > return 1; > } The symptom is then that: - only one trace message appears periodically, - the time between adjacent messages keeps increasing -- implying that some list structure (containing the leaked resources) keeps growing, - the "surface" pointer is ever different. > 18566@1695127471.449586:displaysurface_free surface=0x7f2fcc09a7c0 > 18566@1695127471.529559:displaysurface_free surface=0x7f2fcc9dac10 > 18566@1695127471.659812:displaysurface_free surface=0x7f2fcc441dd0 > 18566@1695127471.839669:displaysurface_free surface=0x7f2fcc0363d0 > 18566@1695127472.069674:displaysurface_free surface=0x7f2fcc413a80 > 18566@1695127472.349580:displaysurface_free surface=0x7f2fcc09cd00 > 18566@1695127472.679783:displaysurface_free surface=0x7f2fcc1395f0 > 18566@1695127473.059848:displaysurface_free surface=0x7f2fcc1cae50 > 18566@1695127473.489724:displaysurface_free surface=0x7f2fcc42fc50 > 18566@1695127473.969791:displaysurface_free surface=0x7f2fcc45dcc0 > 18566@1695127474.499708:displaysurface_free surface=0x7f2fcc70b9d0 > 18566@1695127475.079769:displaysurface_free surface=0x7f2fcc82acc0 > 18566@1695127475.709941:displaysurface_free surface=0x7f2fcc369c00 > 18566@1695127476.389619:displaysurface_free surface=0x7f2fcc32b910 > 18566@1695127477.119772:displaysurface_free surface=0x7f2fcc0d5a20 > 18566@1695127477.899517:displaysurface_free surface=0x7f2fcc086c40 > 18566@1695127478.729962:displaysurface_free surface=0x7f2fccc72020 > 18566@1695127479.609839:displaysurface_free surface=0x7f2fcc185160 > 18566@1695127480.539688:displaysurface_free surface=0x7f2fcc23a7e0 > 18566@1695127481.519759:displaysurface_free surface=0x7f2fcc3ec870 > 18566@1695127482.549930:displaysurface_free surface=0x7f2fcc634960 > 18566@1695127483.629661:displaysurface_free surface=0x7f2fcc26b140 > 18566@1695127484.759987:displaysurface_free surface=0x7f2fcc321700 > 18566@1695127485.940289:displaysurface_free surface=0x7f2fccaad100 We figured this wasn't a CVE-worthy problem, as only small amounts of memory were leaked (the framebuffer itself is mapped from guest RAM, QEMU only allocates administrative structures), plus libvirt restricts QEMU memory footprint anyway, thus the guest can only DoS itself. Plug the leak, by releasing the last prepared (not yet swapped in) display surface, if any, in the fw_cfg DMA write callback. Regarding the "reproducer", with the fix in place, the log is flooded with trace messages (one per fw_cfg write), *and* the trace message alternates between just two "surface" pointer values (i.e., nothing is leaked, the allocator flip-flops between two objects in effect). This issue appears to date back to the introducion of ramfb (995b30179bdc, "hw/display: add ramfb, a simple boot framebuffer living in guest ram", 2018-06-18). Cc: Gerd Hoffmann (maintainer:ramfb) Cc: qemu-stable@nongnu.org Fixes: 995b30179bdc Signed-off-by: Laszlo Ersek Acked-by: Laszlo Ersek Reviewed-by: Gerd Hoffmann Reviewed-by: Marc-André Lureau Message-ID: <20230919131955.27223-1-lersek@redhat.com> --- hw/display/ramfb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/display/ramfb.c b/hw/display/ramfb.c index 79b9754a5820..c2b002d53480 100644 --- a/hw/display/ramfb.c +++ b/hw/display/ramfb.c @@ -97,6 +97,7 @@ static void ramfb_fw_cfg_write(void *dev, off_t offset, size_t len) s->width = width; s->height = height; + qemu_free_displaysurface(s->ds); s->ds = surface; } From 4f7689f0817a717d18cc8aca298990760f27a89b Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 16 Aug 2023 23:07:43 +0200 Subject: [PATCH 142/208] chardev/char-pty: Avoid losing bytes when the other side just (re-)connected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When starting a guest via libvirt with "virsh start --console ...", the first second of the console output is missing. This is especially annoying on s390x that only has a text console by default and no graphical output - if the bios fails to boot here, the information about what went wrong is completely lost. One part of the problem (there is also some things to be done on the libvirt side) is that QEMU only checks with a 1 second timer whether the other side of the pty is already connected, so the first second of the console output is always lost. This likely used to work better in the past, since the code once checked for a re-connection during write, but this has been removed in commit f8278c7d74 ("char-pty: remove the check for connection on write") to avoid some locking. To ease the situation here at least a little bit, let's check with g_poll() whether we could send out the data anyway, even if the connection has not been marked as "connected" yet. The file descriptor is marked as non-blocking anyway since commit fac6688a18 ("Do not hang on full PTY"), so this should not cause any trouble if the other side is not ready for receiving yet. With this patch applied, I can now successfully see the bios output of a s390x guest when running it with "virsh start --console" (with a patched version of virsh that fixes the remaining issues there, too). Reported-by: Marc Hartmayer Signed-off-by: Thomas Huth Reviewed-by: Daniel P. Berrangé Message-Id: <20230816210743.1319018-1-thuth@redhat.com> --- chardev/char-pty.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/chardev/char-pty.c b/chardev/char-pty.c index 4e5deac18aee..cc2f7617fe7f 100644 --- a/chardev/char-pty.c +++ b/chardev/char-pty.c @@ -106,11 +106,27 @@ static void pty_chr_update_read_handler(Chardev *chr) static int char_pty_chr_write(Chardev *chr, const uint8_t *buf, int len) { PtyChardev *s = PTY_CHARDEV(chr); + GPollFD pfd; + int rc; - if (!s->connected) { - return len; + if (s->connected) { + return io_channel_send(s->ioc, buf, len); } - return io_channel_send(s->ioc, buf, len); + + /* + * The other side might already be re-connected, but the timer might + * not have fired yet. So let's check here whether we can write again: + */ + pfd.fd = QIO_CHANNEL_FILE(s->ioc)->fd; + pfd.events = G_IO_OUT; + pfd.revents = 0; + rc = RETRY_ON_EINTR(g_poll(&pfd, 1, 0)); + g_assert(rc >= 0); + if (!(pfd.revents & G_IO_HUP) && (pfd.revents & G_IO_OUT)) { + io_channel_send(s->ioc, buf, len); + } + + return len; } static GSource *pty_chr_add_watch(Chardev *chr, GIOCondition cond) From 5783a530166c0881df6fe680e095e28d962fc198 Mon Sep 17 00:00:00 2001 From: Karim Taha Date: Mon, 25 Sep 2023 21:23:58 +0300 Subject: [PATCH 143/208] bsd-user: define TARGET_RFSPAWN for rfork to use vfork(2) semantics, and fix RLIM_INFINITY RLIM_INFINITY on FreeBSD, OpenBSD and NetBSD has value of ~(1<<63), caculated one way or another. Signed-off-by: Kyle Evans Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-2-kariem.taha2.7@gmail.com> --- bsd-user/syscall_defs.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h index 9c90616baae2..ddd38c13e085 100644 --- a/bsd-user/syscall_defs.h +++ b/bsd-user/syscall_defs.h @@ -130,11 +130,7 @@ struct target_freebsd_timeval { /* * sys/resource.h */ -#if defined(__FreeBSD__) #define TARGET_RLIM_INFINITY RLIM_INFINITY -#else -#define TARGET_RLIM_INFINITY ((abi_ulong)-1) -#endif #define TARGET_RLIMIT_CPU 0 #define TARGET_RLIMIT_FSIZE 1 @@ -390,6 +386,10 @@ struct target_freebsd_flock { int32_t l_sysid; } QEMU_PACKED; +/* sys/unistd.h */ +/* user: vfork(2) semantics, clear signals */ +#define TARGET_RFSPAWN (1U << 31) + #define safe_syscall0(type, name) \ type safe_##name(void) \ { \ From d314ae93f1724fa2f5e9636aa6483acf9fa7505f Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:23:59 +0300 Subject: [PATCH 144/208] bsd-user: Define procctl(2) related structs Implement procctl flags and related structs: struct target_procctl_reaper_status struct target_procctl_reaper_pidinfo struct target_procctl_reaper_pids struct target_procctl_reaper_kill Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-3-kariem.taha2.7@gmail.com> --- bsd-user/syscall_defs.h | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h index ddd38c13e085..a3bc738ff891 100644 --- a/bsd-user/syscall_defs.h +++ b/bsd-user/syscall_defs.h @@ -390,6 +390,48 @@ struct target_freebsd_flock { /* user: vfork(2) semantics, clear signals */ #define TARGET_RFSPAWN (1U << 31) +/* + * from sys/procctl.h + */ +#define TARGET_PROC_SPROTECT 1 +#define TARGET_PROC_REAP_ACQUIRE 2 +#define TARGET_PROC_REAP_RELEASE 3 +#define TARGET_PROC_REAP_STATUS 4 +#define TARGET_PROC_REAP_GETPIDS 5 +#define TARGET_PROC_REAP_KILL 6 + +struct target_procctl_reaper_status { + uint32_t rs_flags; + uint32_t rs_children; + uint32_t rs_descendants; + uint32_t rs_reaper; + uint32_t rs_pid; + uint32_t rs_pad0[15]; +}; + +struct target_procctl_reaper_pidinfo { + uint32_t pi_pid; + uint32_t pi_subtree; + uint32_t pi_flags; + uint32_t pi_pad0[15]; +}; + +struct target_procctl_reaper_pids { + uint32_t rp_count; + uint32_t rp_pad0[15]; + abi_ulong rp_pids; +}; + +struct target_procctl_reaper_kill { + int32_t rk_sig; + uint32_t rk_flags; + uint32_t rk_subtree; + uint32_t rk_killed; + uint32_t rk_fpid; + uint32_t rk_pad0[15]; +}; + + #define safe_syscall0(type, name) \ type safe_##name(void) \ { \ From 3f254cf203e7bebc3758058802f834d9ba6ca3dc Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:00 +0300 Subject: [PATCH 145/208] bsd-user: Implement host_to_target_siginfo. Used in wait6 system call Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-4-kariem.taha2.7@gmail.com> --- bsd-user/signal-common.h | 1 + bsd-user/signal.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/bsd-user/signal-common.h b/bsd-user/signal-common.h index c044e8116533..77d7c7a78b7f 100644 --- a/bsd-user/signal-common.h +++ b/bsd-user/signal-common.h @@ -35,6 +35,7 @@ int do_sigaction(int sig, const struct target_sigaction *act, abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp); long do_sigreturn(CPUArchState *env, abi_ulong addr); void force_sig_fault(int sig, int code, abi_ulong addr); +void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info); int host_to_target_signal(int sig); void host_to_target_sigset(target_sigset_t *d, const sigset_t *s); void process_pending_signals(CPUArchState *env); diff --git a/bsd-user/signal.c b/bsd-user/signal.c index b6beab659e15..ea82241b70be 100644 --- a/bsd-user/signal.c +++ b/bsd-user/signal.c @@ -311,6 +311,12 @@ static void tswap_siginfo(target_siginfo_t *tinfo, const target_siginfo_t *info) } } +void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info) +{ + host_to_target_siginfo_noswap(tinfo, info); + tswap_siginfo(tinfo, tinfo); +} + int block_signals(void) { TaskState *ts = (TaskState *)thread_cpu->opaque; From cc47390ce7553b29bc8fb12f171836ce5dbf61f5 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:01 +0300 Subject: [PATCH 146/208] bsd-user: Add freebsd_exec_common and do_freebsd_procctl to qemu.h. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-5-kariem.taha2.7@gmail.com> --- bsd-user/qemu.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index d9507137cca6..41c7bd31d3c4 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -249,6 +249,12 @@ abi_long get_errno(abi_long ret); bool is_error(abi_long ret); int host_to_target_errno(int err); +/* os-proc.c */ +abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp, + abi_ulong guest_envp, int do_fexec); +abi_long do_freebsd_procctl(void *cpu_env, int idtype, abi_ulong arg2, + abi_ulong arg3, abi_ulong arg4, abi_ulong arg5, abi_ulong arg6); + /* os-sys.c */ abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen, abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen); From 00bff01fc09c5e3aed4d35842ebc3dbc36a56ee9 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:02 +0300 Subject: [PATCH 147/208] bsd-user: add extern declarations for bsd-proc.c conversion functions Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-6-kariem.taha2.7@gmail.com> --- bsd-user/qemu-bsd.h | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 bsd-user/qemu-bsd.h diff --git a/bsd-user/qemu-bsd.h b/bsd-user/qemu-bsd.h new file mode 100644 index 000000000000..b93a0b7fd5bf --- /dev/null +++ b/bsd-user/qemu-bsd.h @@ -0,0 +1,38 @@ +/* + * BSD conversion extern declarations + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef QEMU_BSD_H +#define QEMU_BSD_H + +#include +#include + +/* bsd-proc.c */ +int target_to_host_resource(int code); +rlim_t target_to_host_rlim(abi_llong target_rlim); +abi_llong host_to_target_rlim(rlim_t rlim); +abi_long host_to_target_rusage(abi_ulong target_addr, + const struct rusage *rusage); +abi_long host_to_target_wrusage(abi_ulong target_addr, + const struct __wrusage *wrusage); +int host_to_target_waitstatus(int status); +void h2g_rusage(const struct rusage *rusage, + struct target_freebsd_rusage *target_rusage); + +#endif /* QEMU_BSD_H */ From 0caa37687882569163ed5984d554938fb327ea3c Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:03 +0300 Subject: [PATCH 148/208] bsd-user: Implement target_to_host_resource conversion function Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-7-kariem.taha2.7@gmail.com> --- bsd-user/bsd-proc.c | 40 ++++++++++++++++++++++++++++++++++++++++ bsd-user/bsd-proc.h | 4 ++++ bsd-user/meson.build | 6 ++++++ 3 files changed, 50 insertions(+) create mode 100644 bsd-user/bsd-proc.c diff --git a/bsd-user/bsd-proc.c b/bsd-user/bsd-proc.c new file mode 100644 index 000000000000..68410a0aa9dd --- /dev/null +++ b/bsd-user/bsd-proc.c @@ -0,0 +1,40 @@ +/* + * BSD process related system call helpers + * + * Copyright (c) 2013-14 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +#include "qemu/osdep.h" + +#include +#include +#include +#include +#include + +#include "qemu.h" +#include "qemu-bsd.h" +#include "signal-common.h" + +#include "bsd-proc.h" + +/* + * resource/rusage conversion + */ +int target_to_host_resource(int code) +{ + return code; +} + diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h index a1061bffb8f7..048773a75dd6 100644 --- a/bsd-user/bsd-proc.h +++ b/bsd-user/bsd-proc.h @@ -22,6 +22,10 @@ #include +#include "qemu-bsd.h" +#include "gdbstub/syscalls.h" +#include "qemu/plugin.h" + /* exit(2) */ static inline abi_long do_bsd_exit(void *cpu_env, abi_long arg1) { diff --git a/bsd-user/meson.build b/bsd-user/meson.build index 5243122fc56d..b97fce14722f 100644 --- a/bsd-user/meson.build +++ b/bsd-user/meson.build @@ -7,6 +7,7 @@ bsd_user_ss = ss.source_set() common_user_inc += include_directories('include') bsd_user_ss.add(files( + 'bsd-proc.c', 'bsdload.c', 'elfload.c', 'main.c', @@ -16,6 +17,11 @@ bsd_user_ss.add(files( 'uaccess.c', )) +elf = cc.find_library('elf', required: true) +procstat = cc.find_library('procstat', required: true) +kvm = cc.find_library('kvm', required: true) +bsd_user_ss.add(elf, procstat, kvm) + # Pull in the OS-specific build glue, if any subdir(targetos) From 550fc7018993d4c21092d6882e4846fc3151d3ed Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:04 +0300 Subject: [PATCH 149/208] bsd-user: Implement target_to_host_rlim and host_to_target_rlim conversion. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-8-kariem.taha2.7@gmail.com> --- bsd-user/bsd-proc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bsd-user/bsd-proc.c b/bsd-user/bsd-proc.c index 68410a0aa9dd..19e39a2f764b 100644 --- a/bsd-user/bsd-proc.c +++ b/bsd-user/bsd-proc.c @@ -38,3 +38,13 @@ int target_to_host_resource(int code) return code; } +rlim_t target_to_host_rlim(abi_llong target_rlim) +{ + return tswap64(target_rlim); +} + +abi_llong host_to_target_rlim(rlim_t rlim) +{ + return tswap64(rlim); +} + From 66c51d63d408fe4130d3fb63524d7a009e1e01a6 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:05 +0300 Subject: [PATCH 150/208] bsd-user: Implement host_to_target_rusage and host_to_target_wrusage. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-9-kariem.taha2.7@gmail.com> --- bsd-user/bsd-proc.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/bsd-user/bsd-proc.c b/bsd-user/bsd-proc.c index 19e39a2f764b..aa386ff48200 100644 --- a/bsd-user/bsd-proc.c +++ b/bsd-user/bsd-proc.c @@ -48,3 +48,57 @@ abi_llong host_to_target_rlim(rlim_t rlim) return tswap64(rlim); } +void h2g_rusage(const struct rusage *rusage, + struct target_freebsd_rusage *target_rusage) +{ + __put_user(rusage->ru_utime.tv_sec, &target_rusage->ru_utime.tv_sec); + __put_user(rusage->ru_utime.tv_usec, &target_rusage->ru_utime.tv_usec); + + __put_user(rusage->ru_stime.tv_sec, &target_rusage->ru_stime.tv_sec); + __put_user(rusage->ru_stime.tv_usec, &target_rusage->ru_stime.tv_usec); + + __put_user(rusage->ru_maxrss, &target_rusage->ru_maxrss); + __put_user(rusage->ru_idrss, &target_rusage->ru_idrss); + __put_user(rusage->ru_idrss, &target_rusage->ru_idrss); + __put_user(rusage->ru_isrss, &target_rusage->ru_isrss); + __put_user(rusage->ru_minflt, &target_rusage->ru_minflt); + __put_user(rusage->ru_majflt, &target_rusage->ru_majflt); + __put_user(rusage->ru_nswap, &target_rusage->ru_nswap); + __put_user(rusage->ru_inblock, &target_rusage->ru_inblock); + __put_user(rusage->ru_oublock, &target_rusage->ru_oublock); + __put_user(rusage->ru_msgsnd, &target_rusage->ru_msgsnd); + __put_user(rusage->ru_msgrcv, &target_rusage->ru_msgrcv); + __put_user(rusage->ru_nsignals, &target_rusage->ru_nsignals); + __put_user(rusage->ru_nvcsw, &target_rusage->ru_nvcsw); + __put_user(rusage->ru_nivcsw, &target_rusage->ru_nivcsw); +} + +abi_long host_to_target_rusage(abi_ulong target_addr, + const struct rusage *rusage) +{ + struct target_freebsd_rusage *target_rusage; + + if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0)) { + return -TARGET_EFAULT; + } + h2g_rusage(rusage, target_rusage); + unlock_user_struct(target_rusage, target_addr, 1); + + return 0; +} + +abi_long host_to_target_wrusage(abi_ulong target_addr, + const struct __wrusage *wrusage) +{ + struct target_freebsd__wrusage *target_wrusage; + + if (!lock_user_struct(VERIFY_WRITE, target_wrusage, target_addr, 0)) { + return -TARGET_EFAULT; + } + h2g_rusage(&wrusage->wru_self, &target_wrusage->wru_self); + h2g_rusage(&wrusage->wru_children, &target_wrusage->wru_children); + unlock_user_struct(target_wrusage, target_addr, 1); + + return 0; +} + From 3f44e273ff530ae9885b64791779ced571233d1d Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:06 +0300 Subject: [PATCH 151/208] bsd-user: Implement host_to_target_waitstatus conversion. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-10-kariem.taha2.7@gmail.com> --- bsd-user/bsd-proc.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/bsd-user/bsd-proc.c b/bsd-user/bsd-proc.c index aa386ff48200..19f6efe1f78d 100644 --- a/bsd-user/bsd-proc.c +++ b/bsd-user/bsd-proc.c @@ -102,3 +102,20 @@ abi_long host_to_target_wrusage(abi_ulong target_addr, return 0; } +/* + * wait status conversion. + * + * Map host to target signal numbers for the wait family of syscalls. + * Assume all other status bits are the same. + */ +int host_to_target_waitstatus(int status) +{ + if (WIFSIGNALED(status)) { + return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f); + } + if (WIFSTOPPED(status)) { + return (host_to_target_signal(WSTOPSIG(status)) << 8) | (status & 0xff); + } + return status; +} + From b623031ca60b23dbb8a573306495e7d99821a9af Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 25 Sep 2023 21:24:07 +0300 Subject: [PATCH 152/208] bsd-user: Get number of cpus. Signed-off-by: Kyle Evans Signed-off-by: Karim Taha Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-11-kariem.taha2.7@gmail.com> --- bsd-user/bsd-proc.c | 24 ++++++++++++++++++++++++ bsd-user/bsd-proc.h | 2 ++ 2 files changed, 26 insertions(+) diff --git a/bsd-user/bsd-proc.c b/bsd-user/bsd-proc.c index 19f6efe1f78d..ca3c1bf94f4a 100644 --- a/bsd-user/bsd-proc.c +++ b/bsd-user/bsd-proc.c @@ -119,3 +119,27 @@ int host_to_target_waitstatus(int status) return status; } +int bsd_get_ncpu(void) +{ + int ncpu = -1; + cpuset_t mask; + + CPU_ZERO(&mask); + + if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(mask), + &mask) == 0) { + ncpu = CPU_COUNT(&mask); + } + + if (ncpu == -1) { + ncpu = sysconf(_SC_NPROCESSORS_ONLN); + } + + if (ncpu == -1) { + gemu_log("XXX Missing bsd_get_ncpu() implementation\n"); + ncpu = 1; + } + + return ncpu; +} + diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h index 048773a75dd6..b6225e520eae 100644 --- a/bsd-user/bsd-proc.h +++ b/bsd-user/bsd-proc.h @@ -26,6 +26,8 @@ #include "gdbstub/syscalls.h" #include "qemu/plugin.h" +int bsd_get_ncpu(void); + /* exit(2) */ static inline abi_long do_bsd_exit(void *cpu_env, abi_long arg1) { From a478416dc89f9eaceb8d6550efd8417a965153a2 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:08 +0300 Subject: [PATCH 153/208] bsd-user: Implement getgroups(2) and setgroups(2) system calls. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-12-kariem.taha2.7@gmail.com> --- bsd-user/bsd-proc.h | 44 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 9 +++++++ 2 files changed, 53 insertions(+) diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h index b6225e520eae..7b25aa19829b 100644 --- a/bsd-user/bsd-proc.h +++ b/bsd-user/bsd-proc.h @@ -41,4 +41,48 @@ static inline abi_long do_bsd_exit(void *cpu_env, abi_long arg1) return 0; } +/* getgroups(2) */ +static inline abi_long do_bsd_getgroups(abi_long gidsetsize, abi_long arg2) +{ + abi_long ret; + uint32_t *target_grouplist; + g_autofree gid_t *grouplist; + int i; + + grouplist = g_try_new(gid_t, gidsetsize); + ret = get_errno(getgroups(gidsetsize, grouplist)); + if (gidsetsize != 0) { + if (!is_error(ret)) { + target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0); + if (!target_grouplist) { + return -TARGET_EFAULT; + } + for (i = 0; i < ret; i++) { + target_grouplist[i] = tswap32(grouplist[i]); + } + unlock_user(target_grouplist, arg2, gidsetsize * 2); + } + } + return ret; +} + +/* setgroups(2) */ +static inline abi_long do_bsd_setgroups(abi_long gidsetsize, abi_long arg2) +{ + uint32_t *target_grouplist; + g_autofree gid_t *grouplist; + int i; + + grouplist = g_try_new(gid_t, gidsetsize); + target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1); + if (!target_grouplist) { + return -TARGET_EFAULT; + } + for (i = 0; i < gidsetsize; i++) { + grouplist[i] = tswap32(target_grouplist[i]); + } + unlock_user(target_grouplist, arg2, 0); + return get_errno(setgroups(gidsetsize, grouplist)); +} + #endif /* !BSD_PROC_H_ */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index fa60df529efa..535e6287bde2 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -223,6 +223,15 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_exit(cpu_env, arg1); break; + case TARGET_FREEBSD_NR_getgroups: /* getgroups(2) */ + ret = do_bsd_getgroups(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_setgroups: /* setgroups(2) */ + ret = do_bsd_setgroups(arg1, arg2); + break; + + /* * File system calls. */ From 82fe5f3a3454fe19cfff1b52430ef783da10719a Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:09 +0300 Subject: [PATCH 154/208] bsd-user: Implement umask(2), setlogin(2) and getlogin(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-13-kariem.taha2.7@gmail.com> --- bsd-user/bsd-proc.h | 39 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 12 +++++++++++ 2 files changed, 51 insertions(+) diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h index 7b25aa19829b..cb7c69acb0c7 100644 --- a/bsd-user/bsd-proc.h +++ b/bsd-user/bsd-proc.h @@ -26,6 +26,7 @@ #include "gdbstub/syscalls.h" #include "qemu/plugin.h" +extern int _getlogin(char*, int); int bsd_get_ncpu(void); /* exit(2) */ @@ -85,4 +86,42 @@ static inline abi_long do_bsd_setgroups(abi_long gidsetsize, abi_long arg2) return get_errno(setgroups(gidsetsize, grouplist)); } +/* umask(2) */ +static inline abi_long do_bsd_umask(abi_long arg1) +{ + return get_errno(umask(arg1)); +} + +/* setlogin(2) */ +static inline abi_long do_bsd_setlogin(abi_long arg1) +{ + abi_long ret; + void *p; + + p = lock_user_string(arg1); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(setlogin(p)); + unlock_user(p, arg1, 0); + + return ret; +} + +/* getlogin(2) */ +static inline abi_long do_bsd_getlogin(abi_long arg1, abi_long arg2) +{ + abi_long ret; + void *p; + + p = lock_user(VERIFY_WRITE, arg1, arg2, 0); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(_getlogin(p, arg2)); + unlock_user(p, arg1, arg2); + + return ret; +} + #endif /* !BSD_PROC_H_ */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 535e6287bde2..44cbf52f0873 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -231,6 +231,18 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_setgroups(arg1, arg2); break; + case TARGET_FREEBSD_NR_umask: /* umask(2) */ + ret = do_bsd_umask(arg1); + break; + + case TARGET_FREEBSD_NR_setlogin: /* setlogin(2) */ + ret = do_bsd_setlogin(arg1); + break; + + case TARGET_FREEBSD_NR_getlogin: /* getlogin(2) */ + ret = do_bsd_getlogin(arg1, arg2); + break; + /* * File system calls. From 59e801efdfce31b62d09793d35e85d3bdad0230c Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:10 +0300 Subject: [PATCH 155/208] bsd-user: Implement getrusage(2). Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-14-kariem.taha2.7@gmail.com> --- bsd-user/bsd-proc.h | 13 +++++++++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h index cb7c69acb0c7..133c1b0eaf8c 100644 --- a/bsd-user/bsd-proc.h +++ b/bsd-user/bsd-proc.h @@ -124,4 +124,17 @@ static inline abi_long do_bsd_getlogin(abi_long arg1, abi_long arg2) return ret; } +/* getrusage(2) */ +static inline abi_long do_bsd_getrusage(abi_long who, abi_ulong target_addr) +{ + abi_long ret; + struct rusage rusage; + + ret = get_errno(getrusage(who, &rusage)); + if (!is_error(ret)) { + host_to_target_rusage(target_addr, &rusage); + } + return ret; +} + #endif /* !BSD_PROC_H_ */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 44cbf52f0873..5d8693ed550e 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -243,6 +243,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_getlogin(arg1, arg2); break; + case TARGET_FREEBSD_NR_getrusage: /* getrusage(2) */ + ret = do_bsd_getrusage(arg1, arg2); + break; + /* * File system calls. From faba8e123f41902edf762bb12054f096713a5338 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:11 +0300 Subject: [PATCH 156/208] bsd-user: Implement getrlimit(2) and setrlimit(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-15-kariem.taha2.7@gmail.com> --- bsd-user/bsd-proc.h | 59 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 8 +++++ 2 files changed, 67 insertions(+) diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h index 133c1b0eaf8c..38d1324034c1 100644 --- a/bsd-user/bsd-proc.h +++ b/bsd-user/bsd-proc.h @@ -137,4 +137,63 @@ static inline abi_long do_bsd_getrusage(abi_long who, abi_ulong target_addr) return ret; } +/* getrlimit(2) */ +static inline abi_long do_bsd_getrlimit(abi_long arg1, abi_ulong arg2) +{ + abi_long ret; + int resource = target_to_host_resource(arg1); + struct target_rlimit *target_rlim; + struct rlimit rlim; + + switch (resource) { + case RLIMIT_STACK: + rlim.rlim_cur = target_dflssiz; + rlim.rlim_max = target_maxssiz; + ret = 0; + break; + + case RLIMIT_DATA: + rlim.rlim_cur = target_dfldsiz; + rlim.rlim_max = target_maxdsiz; + ret = 0; + break; + + default: + ret = get_errno(getrlimit(resource, &rlim)); + break; + } + if (!is_error(ret)) { + if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) { + return -TARGET_EFAULT; + } + target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur); + target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max); + unlock_user_struct(target_rlim, arg2, 1); + } + return ret; +} + +/* setrlimit(2) */ +static inline abi_long do_bsd_setrlimit(abi_long arg1, abi_ulong arg2) +{ + abi_long ret; + int resource = target_to_host_resource(arg1); + struct target_rlimit *target_rlim; + struct rlimit rlim; + + if (RLIMIT_STACK == resource) { + /* XXX We should, maybe, allow the stack size to shrink */ + ret = -TARGET_EPERM; + } else { + if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1)) { + return -TARGET_EFAULT; + } + rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur); + rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max); + unlock_user_struct(target_rlim, arg2, 0); + ret = get_errno(setrlimit(resource, &rlim)); + } + return ret; +} + #endif /* !BSD_PROC_H_ */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 5d8693ed550e..5cb608623039 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -247,6 +247,14 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_getrusage(arg1, arg2); break; + case TARGET_FREEBSD_NR_getrlimit: /* getrlimit(2) */ + ret = do_bsd_getrlimit(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_setrlimit: /* setrlimit(2) */ + ret = do_bsd_setrlimit(arg1, arg2); + break; + /* * File system calls. From e4446e0a2c8b4f32d53694a85ebdedc06cb69499 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:12 +0300 Subject: [PATCH 157/208] bsd-user: Implement several get/set system calls: getpid(2), getppid(2), getpgrp(2) setreuid(2), setregid(2) getuid(2), geteuid(2), getgid(2), getegid(2), getpgid(2) setuid(2), seteuid(2), setgid(2), setegid(2), setpgid(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-16-kariem.taha2.7@gmail.com> --- bsd-user/bsd-proc.h | 90 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 60 +++++++++++++++++++++++ 2 files changed, 150 insertions(+) diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h index 38d1324034c1..6ff07c0ac360 100644 --- a/bsd-user/bsd-proc.h +++ b/bsd-user/bsd-proc.h @@ -196,4 +196,94 @@ static inline abi_long do_bsd_setrlimit(abi_long arg1, abi_ulong arg2) return ret; } +/* getpid(2) */ +static inline abi_long do_bsd_getpid(void) +{ + return get_errno(getpid()); +} + +/* getppid(2) */ +static inline abi_long do_bsd_getppid(void) +{ + return get_errno(getppid()); +} + +/* getuid(2) */ +static inline abi_long do_bsd_getuid(void) +{ + return get_errno(getuid()); +} + +/* geteuid(2) */ +static inline abi_long do_bsd_geteuid(void) +{ + return get_errno(geteuid()); +} + +/* getgid(2) */ +static inline abi_long do_bsd_getgid(void) +{ + return get_errno(getgid()); +} + +/* getegid(2) */ +static inline abi_long do_bsd_getegid(void) +{ + return get_errno(getegid()); +} + +/* setuid(2) */ +static inline abi_long do_bsd_setuid(abi_long arg1) +{ + return get_errno(setuid(arg1)); +} + +/* seteuid(2) */ +static inline abi_long do_bsd_seteuid(abi_long arg1) +{ + return get_errno(seteuid(arg1)); +} + +/* setgid(2) */ +static inline abi_long do_bsd_setgid(abi_long arg1) +{ + return get_errno(setgid(arg1)); +} + +/* setegid(2) */ +static inline abi_long do_bsd_setegid(abi_long arg1) +{ + return get_errno(setegid(arg1)); +} + +/* getpgid(2) */ +static inline abi_long do_bsd_getpgid(pid_t pid) +{ + return get_errno(getpgid(pid)); +} + +/* setpgid(2) */ +static inline abi_long do_bsd_setpgid(int pid, int pgrp) +{ + return get_errno(setpgid(pid, pgrp)); +} + +/* getpgrp(2) */ +static inline abi_long do_bsd_getpgrp(void) +{ + return get_errno(getpgrp()); +} + +/* setreuid(2) */ +static inline abi_long do_bsd_setreuid(abi_long arg1, abi_long arg2) +{ + return get_errno(setreuid(arg1, arg2)); +} + +/* setregid(2) */ +static inline abi_long do_bsd_setregid(abi_long arg1, abi_long arg2) +{ + return get_errno(setregid(arg1, arg2)); +} + #endif /* !BSD_PROC_H_ */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 5cb608623039..7565e69e76da 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -255,6 +255,66 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_setrlimit(arg1, arg2); break; + case TARGET_FREEBSD_NR_getpid: /* getpid(2) */ + ret = do_bsd_getpid(); + break; + + case TARGET_FREEBSD_NR_getppid: /* getppid(2) */ + ret = do_bsd_getppid(); + break; + + case TARGET_FREEBSD_NR_getuid: /* getuid(2) */ + ret = do_bsd_getuid(); + break; + + case TARGET_FREEBSD_NR_geteuid: /* geteuid(2) */ + ret = do_bsd_geteuid(); + break; + + case TARGET_FREEBSD_NR_getgid: /* getgid(2) */ + ret = do_bsd_getgid(); + break; + + case TARGET_FREEBSD_NR_getegid: /* getegid(2) */ + ret = do_bsd_getegid(); + break; + + case TARGET_FREEBSD_NR_setuid: /* setuid(2) */ + ret = do_bsd_setuid(arg1); + break; + + case TARGET_FREEBSD_NR_seteuid: /* seteuid(2) */ + ret = do_bsd_seteuid(arg1); + break; + + case TARGET_FREEBSD_NR_setgid: /* setgid(2) */ + ret = do_bsd_setgid(arg1); + break; + + case TARGET_FREEBSD_NR_setegid: /* setegid(2) */ + ret = do_bsd_setegid(arg1); + break; + + case TARGET_FREEBSD_NR_getpgrp: /* getpgrp(2) */ + ret = do_bsd_getpgrp(); + break; + + case TARGET_FREEBSD_NR_getpgid: /* getpgid(2) */ + ret = do_bsd_getpgid(arg1); + break; + + case TARGET_FREEBSD_NR_setpgid: /* setpgid(2) */ + ret = do_bsd_setpgid(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_setreuid: /* setreuid(2) */ + ret = do_bsd_setreuid(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_setregid: /* setregid(2) */ + ret = do_bsd_setregid(arg1, arg2); + break; + /* * File system calls. From 932683c3d421a2057e15cd7f87ad781c3d65fc95 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:13 +0300 Subject: [PATCH 158/208] bsd-user: Implement get/set[resuid/resgid/sid] and issetugid. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-17-kariem.taha2.7@gmail.com> --- bsd-user/bsd-proc.h | 76 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 28 +++++++++++++ 2 files changed, 104 insertions(+) diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h index 6ff07c0ac360..a5f301c72ffb 100644 --- a/bsd-user/bsd-proc.h +++ b/bsd-user/bsd-proc.h @@ -286,4 +286,80 @@ static inline abi_long do_bsd_setregid(abi_long arg1, abi_long arg2) return get_errno(setregid(arg1, arg2)); } +/* setresgid(2) */ +static inline abi_long do_bsd_setresgid(gid_t rgid, gid_t egid, gid_t sgid) +{ + return get_errno(setresgid(rgid, egid, sgid)); +} + +/* setresuid(2) */ +static inline abi_long do_bsd_setresuid(uid_t ruid, uid_t euid, uid_t suid) +{ + return get_errno(setresuid(ruid, euid, suid)); +} + +/* getresuid(2) */ +static inline abi_long do_bsd_getresuid(abi_ulong arg1, abi_ulong arg2, + abi_ulong arg3) +{ + abi_long ret; + uid_t ruid, euid, suid; + + ret = get_errno(getresuid(&ruid, &euid, &suid)); + if (is_error(ret)) { + return ret; + } + if (put_user_s32(ruid, arg1)) { + return -TARGET_EFAULT; + } + if (put_user_s32(euid, arg2)) { + return -TARGET_EFAULT; + } + if (put_user_s32(suid, arg3)) { + return -TARGET_EFAULT; + } + return ret; +} + +/* getresgid(2) */ +static inline abi_long do_bsd_getresgid(abi_ulong arg1, abi_ulong arg2, + abi_ulong arg3) +{ + abi_long ret; + uid_t ruid, euid, suid; + + ret = get_errno(getresgid(&ruid, &euid, &suid)); + if (is_error(ret)) { + return ret; + } + if (put_user_s32(ruid, arg1)) { + return -TARGET_EFAULT; + } + if (put_user_s32(euid, arg2)) { + return -TARGET_EFAULT; + } + if (put_user_s32(suid, arg3)) { + return -TARGET_EFAULT; + } + return ret; +} + +/* getsid(2) */ +static inline abi_long do_bsd_getsid(abi_long arg1) +{ + return get_errno(getsid(arg1)); +} + +/* setsid(2) */ +static inline abi_long do_bsd_setsid(void) +{ + return get_errno(setsid()); +} + +/* issetugid(2) */ +static inline abi_long do_bsd_issetugid(void) +{ + return get_errno(issetugid()); +} + #endif /* !BSD_PROC_H_ */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 7565e69e76da..7b51f4f16e42 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -315,6 +315,34 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_setregid(arg1, arg2); break; + case TARGET_FREEBSD_NR_getresuid: /* getresuid(2) */ + ret = do_bsd_getresuid(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_getresgid: /* getresgid(2) */ + ret = do_bsd_getresgid(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_setresuid: /* setresuid(2) */ + ret = do_bsd_setresuid(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_setresgid: /* setresgid(2) */ + ret = do_bsd_setresgid(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_getsid: /* getsid(2) */ + ret = do_bsd_getsid(arg1); + break; + + case TARGET_FREEBSD_NR_setsid: /* setsid(2) */ + ret = do_bsd_setsid(); + break; + + case TARGET_FREEBSD_NR_issetugid: /* issetugid(2) */ + ret = do_bsd_issetugid(); + break; + /* * File system calls. From 615ad41c614bf0f2011bba43116434b66e40abc0 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:14 +0300 Subject: [PATCH 159/208] bsd-user: Add stubs for profil(2), ktrace(2), utrace(2) and ptrace(2). Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-18-kariem.taha2.7@gmail.com> --- bsd-user/bsd-proc.h | 28 ++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 16 ++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h index a5f301c72ffb..2c1a9ae22fac 100644 --- a/bsd-user/bsd-proc.h +++ b/bsd-user/bsd-proc.h @@ -362,4 +362,32 @@ static inline abi_long do_bsd_issetugid(void) return get_errno(issetugid()); } +/* profil(2) */ +static inline abi_long do_bsd_profil(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4) +{ + return -TARGET_ENOSYS; +} + +/* ktrace(2) */ +static inline abi_long do_bsd_ktrace(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4) +{ + return -TARGET_ENOSYS; +} + +/* utrace(2) */ +static inline abi_long do_bsd_utrace(abi_long arg1, abi_long arg2) +{ + return -TARGET_ENOSYS; +} + + +/* ptrace(2) */ +static inline abi_long do_bsd_ptrace(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4) +{ + return -TARGET_ENOSYS; +} + #endif /* !BSD_PROC_H_ */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 7b51f4f16e42..1a760b13808d 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -343,6 +343,22 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_issetugid(); break; + case TARGET_FREEBSD_NR_profil: /* profil(2) */ + ret = do_bsd_profil(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_ktrace: /* ktrace(2) */ + ret = do_bsd_ktrace(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_utrace: /* utrace(2) */ + ret = do_bsd_utrace(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_ptrace: /* ptrace(2) */ + ret = do_bsd_ptrace(arg1, arg2, arg3, arg4); + break; + /* * File system calls. From ff26637260d059f5b37d32f00d7881a8c21a06f9 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:15 +0300 Subject: [PATCH 160/208] bsd-user: Implement getpriority(2) and setpriority(2). Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-19-kariem.taha2.7@gmail.com> --- bsd-user/bsd-proc.h | 24 ++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 8 ++++++++ 2 files changed, 32 insertions(+) diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h index 2c1a9ae22fac..9a8912361f67 100644 --- a/bsd-user/bsd-proc.h +++ b/bsd-user/bsd-proc.h @@ -390,4 +390,28 @@ static inline abi_long do_bsd_ptrace(abi_long arg1, abi_long arg2, return -TARGET_ENOSYS; } +/* getpriority(2) */ +static inline abi_long do_bsd_getpriority(abi_long which, abi_long who) +{ + abi_long ret; + /* + * Note that negative values are valid for getpriority, so we must + * differentiate based on errno settings. + */ + errno = 0; + ret = getpriority(which, who); + if (ret == -1 && errno != 0) { + return -host_to_target_errno(errno); + } + + return ret; +} + +/* setpriority(2) */ +static inline abi_long do_bsd_setpriority(abi_long which, abi_long who, + abi_long prio) +{ + return get_errno(setpriority(which, who, prio)); +} + #endif /* !BSD_PROC_H_ */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 1a760b13808d..71a2657dd0f4 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -359,6 +359,14 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_ptrace(arg1, arg2, arg3, arg4); break; + case TARGET_FREEBSD_NR_getpriority: /* getpriority(2) */ + ret = do_bsd_getpriority(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_setpriority: /* setpriority(2) */ + ret = do_bsd_setpriority(arg1, arg2, arg3); + break; + /* * File system calls. From 84d41c5e6dc69be9b3e0fb8ad5f1ff2007e0e8a1 Mon Sep 17 00:00:00 2001 From: Karim Taha Date: Mon, 25 Sep 2023 21:24:16 +0300 Subject: [PATCH 161/208] bsd-user: Implement get_filename_from_fd. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-20-kariem.taha2.7@gmail.com> --- bsd-user/freebsd/meson.build | 1 + bsd-user/freebsd/os-proc.c | 82 ++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 bsd-user/freebsd/os-proc.c diff --git a/bsd-user/freebsd/meson.build b/bsd-user/freebsd/meson.build index f2f047cca31e..8fd6c7cfb821 100644 --- a/bsd-user/freebsd/meson.build +++ b/bsd-user/freebsd/meson.build @@ -1,5 +1,6 @@ bsd_user_ss.add(files( 'os-stat.c', + 'os-proc.c', 'os-sys.c', 'os-syscall.c', )) diff --git a/bsd-user/freebsd/os-proc.c b/bsd-user/freebsd/os-proc.c new file mode 100644 index 000000000000..2603c5c65382 --- /dev/null +++ b/bsd-user/freebsd/os-proc.c @@ -0,0 +1,82 @@ +/* + * FreeBSD process related emulation code + * + * Copyright (c) 2013-15 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +#include "qemu/osdep.h" + +#include +#include +#include +struct kinfo_proc; +#include + +#include "qemu.h" + +/* + * Get the filename for the given file descriptor. + * Note that this may return NULL (fail) if no longer cached in the kernel. + */ +char * +get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len); +char * +get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len) +{ + char *ret = NULL; + unsigned int cnt; + struct procstat *procstat = NULL; + struct kinfo_proc *kp = NULL; + struct filestat_list *head = NULL; + struct filestat *fst; + + procstat = procstat_open_sysctl(); + if (procstat == NULL) { + goto out; + } + + kp = procstat_getprocs(procstat, KERN_PROC_PID, pid, &cnt); + if (kp == NULL) { + goto out; + } + + head = procstat_getfiles(procstat, kp, 0); + if (head == NULL) { + goto out; + } + + STAILQ_FOREACH(fst, head, next) { + if (fd == fst->fs_fd) { + if (fst->fs_path != NULL) { + (void)strlcpy(filename, fst->fs_path, len); + ret = filename; + } + break; + } + } + +out: + if (head != NULL) { + procstat_freefiles(procstat, head); + } + if (kp != NULL) { + procstat_freeprocs(procstat, kp); + } + if (procstat != NULL) { + procstat_close(procstat); + } + return ret; +} + From 8632729060bf840560215c91c8611bd6769deff9 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:17 +0300 Subject: [PATCH 162/208] bsd-user: Implement freebsd_exec_common, used in implementing execve/fexecve. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-21-kariem.taha2.7@gmail.com> --- bsd-user/freebsd/os-proc.c | 181 ++++++++++++++++++++++++++++++++++++- bsd-user/main.c | 2 +- bsd-user/qemu.h | 1 + 3 files changed, 180 insertions(+), 4 deletions(-) diff --git a/bsd-user/freebsd/os-proc.c b/bsd-user/freebsd/os-proc.c index 2603c5c65382..12d78b7fc987 100644 --- a/bsd-user/freebsd/os-proc.c +++ b/bsd-user/freebsd/os-proc.c @@ -30,9 +30,7 @@ struct kinfo_proc; * Get the filename for the given file descriptor. * Note that this may return NULL (fail) if no longer cached in the kernel. */ -char * -get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len); -char * +static char * get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len) { char *ret = NULL; @@ -80,3 +78,180 @@ get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len) return ret; } +/* + * execve/fexecve + */ +abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp, + abi_ulong guest_envp, int do_fexec) +{ + char **argp, **envp, **qargp, **qarg1, **qarg0, **qargend; + int argc, envc; + abi_ulong gp; + abi_ulong addr; + char **q; + int total_size = 0; + void *p; + abi_long ret; + + argc = 0; + for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) { + if (get_user_ual(addr, gp)) { + return -TARGET_EFAULT; + } + if (!addr) { + break; + } + argc++; + } + envc = 0; + for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) { + if (get_user_ual(addr, gp)) { + return -TARGET_EFAULT; + } + if (!addr) { + break; + } + envc++; + } + + qarg0 = argp = g_new0(char *, argc + 9); + /* save the first agrument for the emulator */ + *argp++ = (char *)getprogname(); + qargp = argp; + *argp++ = (char *)getprogname(); + qarg1 = argp; + envp = g_new0(char *, envc + 1); + for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) { + if (get_user_ual(addr, gp)) { + ret = -TARGET_EFAULT; + goto execve_end; + } + if (!addr) { + break; + } + *q = lock_user_string(addr); + if (*q == NULL) { + ret = -TARGET_EFAULT; + goto execve_end; + } + total_size += strlen(*q) + 1; + } + *q++ = NULL; + qargend = q; + + for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) { + if (get_user_ual(addr, gp)) { + ret = -TARGET_EFAULT; + goto execve_end; + } + if (!addr) { + break; + } + *q = lock_user_string(addr); + if (*q == NULL) { + ret = -TARGET_EFAULT; + goto execve_end; + } + total_size += strlen(*q) + 1; + } + *q = NULL; + + /* + * This case will not be caught by the host's execve() if its + * page size is bigger than the target's. + */ + if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) { + ret = -TARGET_E2BIG; + goto execve_end; + } + + if (do_fexec) { + if (((int)path_or_fd > 0 && + is_target_elf_binary((int)path_or_fd)) == 1) { + char execpath[PATH_MAX]; + + /* + * The executable is an elf binary for the target + * arch. execve() it using the emulator if we can + * determine the filename path from the fd. + */ + if (get_filename_from_fd(getpid(), (int)path_or_fd, execpath, + sizeof(execpath)) != NULL) { + memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1)); + qarg1[1] = qarg1[0]; + qarg1[0] = (char *)"-0"; + qarg1 += 2; + qargend += 2; + *qarg1 = execpath; +#ifndef DONT_INHERIT_INTERP_PREFIX + memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1)); + *qarg1++ = (char *)"-L"; + *qarg1++ = (char *)interp_prefix; +#endif + ret = get_errno(execve(qemu_proc_pathname, qargp, envp)); + } else { + /* Getting the filename path failed. */ + ret = -TARGET_EBADF; + goto execve_end; + } + } else { + ret = get_errno(fexecve((int)path_or_fd, argp, envp)); + } + } else { + int fd; + + p = lock_user_string(path_or_fd); + if (p == NULL) { + ret = -TARGET_EFAULT; + goto execve_end; + } + + /* + * Check the header and see if it a target elf binary. If so + * then execute using qemu user mode emulator. + */ + fd = open(p, O_RDONLY | O_CLOEXEC); + if (fd > 0 && is_target_elf_binary(fd) == 1) { + close(fd); + /* execve() as a target binary using emulator. */ + memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1)); + qarg1[1] = qarg1[0]; + qarg1[0] = (char *)"-0"; + qarg1 += 2; + qargend += 2; + *qarg1 = (char *)p; +#ifndef DONT_INHERIT_INTERP_PREFIX + memmove(qarg1 + 2, qarg1, (qargend - qarg1) * sizeof(*qarg1)); + *qarg1++ = (char *)"-L"; + *qarg1++ = (char *)interp_prefix; +#endif + ret = get_errno(execve(qemu_proc_pathname, qargp, envp)); + } else { + close(fd); + /* Execve() as a host native binary. */ + ret = get_errno(execve(p, argp, envp)); + } + unlock_user(p, path_or_fd, 0); + } + +execve_end: + for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) { + if (get_user_ual(addr, gp) || !addr) { + break; + } + unlock_user(*q, addr, 0); + } + + for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) { + if (get_user_ual(addr, gp) || !addr) { + break; + } + unlock_user(*q, addr, 0); + } + + g_free(qarg0); + g_free(envp); + + return ret; +} + diff --git a/bsd-user/main.c b/bsd-user/main.c index f913cb55a729..a12b4be80f1d 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -88,7 +88,7 @@ unsigned long reserved_va = MAX_RESERVED_VA; unsigned long reserved_va; #endif -static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; +const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; const char *qemu_uname_release; char qemu_proc_pathname[PATH_MAX]; /* full path to exeutable */ diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index 41c7bd31d3c4..6047805ae387 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -111,6 +111,7 @@ typedef struct TaskState { } __attribute__((aligned(16))) TaskState; void stop_all_tasks(void); +extern const char *interp_prefix; extern const char *qemu_uname_release; /* From dcaa3dfda379157a1e5148e112a77aa7e1d79c58 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:18 +0300 Subject: [PATCH 163/208] bsd-user: Implement procctl(2) along with necessary conversion functions. Implement t2h_procctl_cmd, h2t_reaper_status, h2t_reaper_pidinfo and h2t/t2h reaper_kill conversion functions. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-22-kariem.taha2.7@gmail.com> --- bsd-user/freebsd/os-proc.c | 223 ++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 3 + 2 files changed, 226 insertions(+) diff --git a/bsd-user/freebsd/os-proc.c b/bsd-user/freebsd/os-proc.c index 12d78b7fc987..4e67ae4d56c1 100644 --- a/bsd-user/freebsd/os-proc.c +++ b/bsd-user/freebsd/os-proc.c @@ -255,3 +255,226 @@ abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp, return ret; } +#include + +static abi_long +t2h_procctl_cmd(int target_cmd, int *host_cmd) +{ + switch (target_cmd) { + case TARGET_PROC_SPROTECT: + *host_cmd = PROC_SPROTECT; + break; + + case TARGET_PROC_REAP_ACQUIRE: + *host_cmd = PROC_REAP_ACQUIRE; + break; + + case TARGET_PROC_REAP_RELEASE: + *host_cmd = PROC_REAP_RELEASE; + break; + + case TARGET_PROC_REAP_STATUS: + *host_cmd = PROC_REAP_STATUS; + break; + + case TARGET_PROC_REAP_KILL: + *host_cmd = PROC_REAP_KILL; + break; + + default: + return -TARGET_EINVAL; + } + + return 0; +} + +static abi_long +h2t_reaper_status(struct procctl_reaper_status *host_rs, + abi_ulong target_rs_addr) +{ + struct target_procctl_reaper_status *target_rs; + + if (!lock_user_struct(VERIFY_WRITE, target_rs, target_rs_addr, 0)) { + return -TARGET_EFAULT; + } + __put_user(host_rs->rs_flags, &target_rs->rs_flags); + __put_user(host_rs->rs_children, &target_rs->rs_children); + __put_user(host_rs->rs_descendants, &target_rs->rs_descendants); + __put_user(host_rs->rs_reaper, &target_rs->rs_reaper); + __put_user(host_rs->rs_pid, &target_rs->rs_pid); + unlock_user_struct(target_rs, target_rs_addr, 1); + + return 0; +} + +static abi_long +t2h_reaper_kill(abi_ulong target_rk_addr, struct procctl_reaper_kill *host_rk) +{ + struct target_procctl_reaper_kill *target_rk; + + if (!lock_user_struct(VERIFY_READ, target_rk, target_rk_addr, 1)) { + return -TARGET_EFAULT; + } + __get_user(host_rk->rk_sig, &target_rk->rk_sig); + __get_user(host_rk->rk_flags, &target_rk->rk_flags); + __get_user(host_rk->rk_subtree, &target_rk->rk_subtree); + __get_user(host_rk->rk_killed, &target_rk->rk_killed); + __get_user(host_rk->rk_fpid, &target_rk->rk_fpid); + unlock_user_struct(target_rk, target_rk_addr, 0); + + return 0; +} + +static abi_long +h2t_reaper_kill(struct procctl_reaper_kill *host_rk, abi_ulong target_rk_addr) +{ + struct target_procctl_reaper_kill *target_rk; + + if (!lock_user_struct(VERIFY_WRITE, target_rk, target_rk_addr, 0)) { + return -TARGET_EFAULT; + } + __put_user(host_rk->rk_sig, &target_rk->rk_sig); + __put_user(host_rk->rk_flags, &target_rk->rk_flags); + __put_user(host_rk->rk_subtree, &target_rk->rk_subtree); + __put_user(host_rk->rk_killed, &target_rk->rk_killed); + __put_user(host_rk->rk_fpid, &target_rk->rk_fpid); + unlock_user_struct(target_rk, target_rk_addr, 1); + + return 0; +} + +static abi_long +h2t_procctl_reaper_pidinfo(struct procctl_reaper_pidinfo *host_pi, + abi_ulong target_pi_addr) +{ + struct target_procctl_reaper_pidinfo *target_pi; + + if (!lock_user_struct(VERIFY_WRITE, target_pi, target_pi_addr, 0)) { + return -TARGET_EFAULT; + } + __put_user(host_pi->pi_pid, &target_pi->pi_pid); + __put_user(host_pi->pi_subtree, &target_pi->pi_subtree); + __put_user(host_pi->pi_flags, &target_pi->pi_flags); + unlock_user_struct(target_pi, target_pi_addr, 1); + + return 0; +} + +abi_long +do_freebsd_procctl(void *cpu_env, int idtype, abi_ulong arg2, abi_ulong arg3, + abi_ulong arg4, abi_ulong arg5, abi_ulong arg6) +{ + abi_long error = 0, target_rp_pids; + void *data; + int host_cmd, flags; + uint32_t u, target_rp_count; + g_autofree union { + struct procctl_reaper_status rs; + struct procctl_reaper_pids rp; + struct procctl_reaper_kill rk; + } host; + struct target_procctl_reaper_pids *target_rp; + id_t id; /* 64-bit */ + int target_cmd; + abi_ulong target_arg; + +#if TARGET_ABI_BITS == 32 + /* See if we need to align the register pairs. */ + if (regpairs_aligned(cpu_env)) { + id = (id_t)target_arg64(arg3, arg4); + target_cmd = (int)arg5; + target_arg = arg6; + } else { + id = (id_t)target_arg64(arg2, arg3); + target_cmd = (int)arg4; + target_arg = arg5; + } +#else + id = (id_t)arg2; + target_cmd = (int)arg3; + target_arg = arg4; +#endif + + error = t2h_procctl_cmd(target_cmd, &host_cmd); + if (error) { + return error; + } + switch (host_cmd) { + case PROC_SPROTECT: + data = &flags; + break; + + case PROC_REAP_ACQUIRE: + case PROC_REAP_RELEASE: + if (target_arg == 0) { + data = NULL; + } else { + error = -TARGET_EINVAL; + } + break; + + case PROC_REAP_STATUS: + data = &host.rs; + break; + + case PROC_REAP_GETPIDS: + if (!lock_user_struct(VERIFY_READ, target_rp, target_arg, 1)) { + return -TARGET_EFAULT; + } + __get_user(target_rp_count, &target_rp->rp_count); + __get_user(target_rp_pids, &target_rp->rp_pids); + unlock_user_struct(target_rp, target_arg, 0); + host.rp.rp_count = target_rp_count; + host.rp.rp_pids = g_try_new(struct procctl_reaper_pidinfo, + target_rp_count); + + if (host.rp.rp_pids == NULL) { + error = -TARGET_ENOMEM; + } else { + data = &host.rp; + } + break; + + case PROC_REAP_KILL: + error = t2h_reaper_kill(target_arg, &host.rk); + break; + } + + if (error) { + return error; + } + error = get_errno(procctl(idtype, id, host_cmd, data)); + + if (error) { + return error; + } + switch (host_cmd) { + case PROC_SPROTECT: + if (put_user_s32(flags, target_arg)) { + return -TARGET_EFAULT; + } + break; + + case PROC_REAP_STATUS: + error = h2t_reaper_status(&host.rs, target_arg); + break; + + case PROC_REAP_GETPIDS: + /* copyout reaper pidinfo */ + for (u = 0; u < target_rp_count; u++) { + error = h2t_procctl_reaper_pidinfo(&host.rp.rp_pids[u], + target_rp_pids + + (u * sizeof(struct target_procctl_reaper_pidinfo))); + if (error) { + break; + } + } + break; + + case PROC_REAP_KILL: + error = h2t_reaper_kill(&host.rk, target_arg); + break; + } + + return error; +} diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 71a2657dd0f4..b7bd0b92a65e 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -367,6 +367,9 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_setpriority(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_procctl: /* procctl(2) */ + ret = do_freebsd_procctl(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6); + break; /* * File system calls. From 36999e6a6bb1e3c7d7d40c751b67d5886f023ee9 Mon Sep 17 00:00:00 2001 From: Karim Taha Date: Mon, 25 Sep 2023 21:24:19 +0300 Subject: [PATCH 164/208] bsd-user: Implement execve(2) and fexecve(2) system calls. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-23-kariem.taha2.7@gmail.com> --- bsd-user/freebsd/os-proc.h | 49 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 11 +++++++- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 bsd-user/freebsd/os-proc.h diff --git a/bsd-user/freebsd/os-proc.h b/bsd-user/freebsd/os-proc.h new file mode 100644 index 000000000000..75ed39f8dddc --- /dev/null +++ b/bsd-user/freebsd/os-proc.h @@ -0,0 +1,49 @@ +/* + * process related system call shims and definitions + * + * Copyright (c) 2013-14 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef BSD_USER_FREEBSD_OS_PROC_H +#define BSD_USER_FREEBSD_OS_PROC_H + +#include +#include +#include +#include +#include +#include +#include + +#include "target_arch_cpu.h" + +/* execve(2) */ +static inline abi_long do_freebsd_execve(abi_ulong path_or_fd, abi_ulong argp, + abi_ulong envp) +{ + + return freebsd_exec_common(path_or_fd, argp, envp, 0); +} + +/* fexecve(2) */ +static inline abi_long do_freebsd_fexecve(abi_ulong path_or_fd, abi_ulong argp, + abi_ulong envp) +{ + + return freebsd_exec_common(path_or_fd, argp, envp, 1); +} + +#endif /* BSD_USER_FREEBSD_OS_PROC_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index b7bd0b92a65e..515eaaf31f1b 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -36,8 +36,9 @@ #include "bsd-file.h" #include "bsd-proc.h" -/* *BSD dependent syscall shims */ +/* BSD dependent syscall shims */ #include "os-stat.h" +#include "os-proc.h" /* I/O */ safe_syscall3(int, open, const char *, path, int, flags, mode_t, mode); @@ -219,6 +220,14 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, /* * process system calls */ + case TARGET_FREEBSD_NR_execve: /* execve(2) */ + ret = do_freebsd_execve(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_fexecve: /* fexecve(2) */ + ret = do_freebsd_fexecve(arg1, arg2, arg3); + break; + case TARGET_FREEBSD_NR_exit: /* exit(2) */ ret = do_bsd_exit(cpu_env, arg1); break; From ae502887cb3e3aa38bc0837cd7580f7a6768a649 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:20 +0300 Subject: [PATCH 165/208] bsd-user: Implement wait4(2) and wait6(2) system calls. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-24-kariem.taha2.7@gmail.com> --- bsd-user/freebsd/os-proc.h | 84 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 15 +++++++ 2 files changed, 99 insertions(+) diff --git a/bsd-user/freebsd/os-proc.h b/bsd-user/freebsd/os-proc.h index 75ed39f8dddc..04bce755e58b 100644 --- a/bsd-user/freebsd/os-proc.h +++ b/bsd-user/freebsd/os-proc.h @@ -30,6 +30,10 @@ #include "target_arch_cpu.h" +pid_t safe_wait4(pid_t wpid, int *status, int options, struct rusage *rusage); +pid_t safe_wait6(idtype_t idtype, id_t id, int *status, int options, + struct __wrusage *wrusage, siginfo_t *infop); + /* execve(2) */ static inline abi_long do_freebsd_execve(abi_ulong path_or_fd, abi_ulong argp, abi_ulong envp) @@ -46,4 +50,84 @@ static inline abi_long do_freebsd_fexecve(abi_ulong path_or_fd, abi_ulong argp, return freebsd_exec_common(path_or_fd, argp, envp, 1); } +/* wait4(2) */ +static inline abi_long do_freebsd_wait4(abi_long arg1, abi_ulong target_status, + abi_long arg3, abi_ulong target_rusage) +{ + abi_long ret; + int status; + struct rusage rusage, *rusage_ptr = NULL; + + if (target_rusage) { + rusage_ptr = &rusage; + } + ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr)); + + if (ret < 0) { + return ret; + } + if (target_status != 0) { + status = host_to_target_waitstatus(status); + if (put_user_s32(status, target_status) != 0) { + return -TARGET_EFAULT; + } + } + if (target_rusage != 0) { + host_to_target_rusage(target_rusage, &rusage); + } + return ret; +} + +/* wait6(2) */ +static inline abi_long do_freebsd_wait6(void *cpu_env, abi_long idtype, + abi_long id1, abi_long id2, + abi_ulong target_status, abi_long options, abi_ulong target_wrusage, + abi_ulong target_infop, abi_ulong pad1) +{ + abi_long ret; + int status; + struct __wrusage wrusage, *wrusage_ptr = NULL; + siginfo_t info; + void *p; + + if (regpairs_aligned(cpu_env) != 0) { + /* printf("shifting args\n"); */ + /* 64-bit id is aligned, so shift all the arguments over by one */ + id1 = id2; + id2 = target_status; + target_status = options; + options = target_wrusage; + target_wrusage = target_infop; + target_infop = pad1; + } + + if (target_wrusage) { + wrusage_ptr = &wrusage; + } + ret = get_errno(safe_wait6(idtype, target_arg64(id1, id2), + &status, options, wrusage_ptr, &info)); + + if (ret < 0) { + return ret; + } + if (target_status != 0) { + status = host_to_target_waitstatus(status); + if (put_user_s32(status, target_status) != 0) { + return -TARGET_EFAULT; + } + } + if (target_wrusage != 0) { + host_to_target_wrusage(target_wrusage, &wrusage); + } + if (target_infop != 0) { + p = lock_user(VERIFY_WRITE, target_infop, sizeof(target_siginfo_t), 0); + if (p == NULL) { + return -TARGET_EFAULT; + } + host_to_target_siginfo(p, &info); + unlock_user(p, target_infop, sizeof(target_siginfo_t)); + } + return ret; +} + #endif /* BSD_USER_FREEBSD_OS_PROC_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 515eaaf31f1b..55e68e481597 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -40,6 +40,12 @@ #include "os-stat.h" #include "os-proc.h" +/* used in os-proc */ +safe_syscall4(pid_t, wait4, pid_t, wpid, int *, status, int, options, + struct rusage *, rusage); +safe_syscall6(pid_t, wait6, idtype_t, idtype, id_t, id, int *, status, int, + options, struct __wrusage *, wrusage, siginfo_t *, infop); + /* I/O */ safe_syscall3(int, open, const char *, path, int, flags, mode_t, mode); safe_syscall4(int, openat, int, fd, const char *, path, int, flags, mode_t, @@ -228,6 +234,15 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_freebsd_fexecve(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_wait4: /* wait4(2) */ + ret = do_freebsd_wait4(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_wait6: /* wait6(2) */ + ret = do_freebsd_wait6(cpu_env, arg1, arg2, arg3, + arg4, arg5, arg6, arg7, arg8); + break; + case TARGET_FREEBSD_NR_exit: /* exit(2) */ ret = do_bsd_exit(cpu_env, arg1); break; From 159e5b0c4bb00ade2d53e6c482ecda59f69fbdde Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:21 +0300 Subject: [PATCH 166/208] bsd-user: Implement setloginclass(2) and getloginclass(2) system calls. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-25-kariem.taha2.7@gmail.com> --- bsd-user/freebsd/os-proc.h | 32 ++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 8 ++++++++ 2 files changed, 40 insertions(+) diff --git a/bsd-user/freebsd/os-proc.h b/bsd-user/freebsd/os-proc.h index 04bce755e58b..2eaba141dcd4 100644 --- a/bsd-user/freebsd/os-proc.h +++ b/bsd-user/freebsd/os-proc.h @@ -130,4 +130,36 @@ static inline abi_long do_freebsd_wait6(void *cpu_env, abi_long idtype, return ret; } +/* setloginclass(2) */ +static inline abi_long do_freebsd_setloginclass(abi_ulong arg1) +{ + abi_long ret; + void *p; + + p = lock_user_string(arg1); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(setloginclass(p)); + unlock_user(p, arg1, 0); + + return ret; +} + +/* getloginclass(2) */ +static inline abi_long do_freebsd_getloginclass(abi_ulong arg1, abi_ulong arg2) +{ + abi_long ret; + void *p; + + p = lock_user(VERIFY_WRITE, arg1, arg2, 0); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(getloginclass(p, arg2)); + unlock_user(p, arg1, arg2); + + return ret; +} + #endif /* BSD_USER_FREEBSD_OS_PROC_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 55e68e481597..d614409e6947 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -375,6 +375,14 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_ktrace(arg1, arg2, arg3, arg4); break; + case TARGET_FREEBSD_NR_setloginclass: /* setloginclass(2) */ + ret = do_freebsd_setloginclass(arg1); + break; + + case TARGET_FREEBSD_NR_getloginclass: /* getloginclass(2) */ + ret = do_freebsd_getloginclass(arg1, arg2); + break; + case TARGET_FREEBSD_NR_utrace: /* utrace(2) */ ret = do_bsd_utrace(arg1, arg2); break; From 0571e3f5e20e4a93b0d59c948bcd89b60033d0be Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:22 +0300 Subject: [PATCH 167/208] bsd-user: Implement pdgetpid(2) and the undocumented setugid. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-26-kariem.taha2.7@gmail.com> --- bsd-user/freebsd/os-proc.h | 23 +++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 8 ++++++++ 2 files changed, 31 insertions(+) diff --git a/bsd-user/freebsd/os-proc.h b/bsd-user/freebsd/os-proc.h index 2eaba141dcd4..42bdd61904b3 100644 --- a/bsd-user/freebsd/os-proc.h +++ b/bsd-user/freebsd/os-proc.h @@ -34,6 +34,8 @@ pid_t safe_wait4(pid_t wpid, int *status, int options, struct rusage *rusage); pid_t safe_wait6(idtype_t idtype, id_t id, int *status, int options, struct __wrusage *wrusage, siginfo_t *infop); +extern int __setugid(int flag); + /* execve(2) */ static inline abi_long do_freebsd_execve(abi_ulong path_or_fd, abi_ulong argp, abi_ulong envp) @@ -162,4 +164,25 @@ static inline abi_long do_freebsd_getloginclass(abi_ulong arg1, abi_ulong arg2) return ret; } +/* pdgetpid(2) */ +static inline abi_long do_freebsd_pdgetpid(abi_long fd, abi_ulong target_pidp) +{ + abi_long ret; + pid_t pid; + + ret = get_errno(pdgetpid(fd, &pid)); + if (!is_error(ret)) { + if (put_user_u32(pid, target_pidp)) { + return -TARGET_EFAULT; + } + } + return ret; +} + +/* undocumented __setugid */ +static inline abi_long do_freebsd___setugid(abi_long arg1) +{ + return -TARGET_ENOSYS; +} + #endif /* BSD_USER_FREEBSD_OS_PROC_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index d614409e6947..99af0f6b156f 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -383,6 +383,14 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_freebsd_getloginclass(arg1, arg2); break; + case TARGET_FREEBSD_NR_pdgetpid: /* pdgetpid(2) */ + ret = do_freebsd_pdgetpid(arg1, arg2); + break; + + case TARGET_FREEBSD_NR___setugid: /* undocumented */ + ret = do_freebsd___setugid(arg1); + break; + case TARGET_FREEBSD_NR_utrace: /* utrace(2) */ ret = do_bsd_utrace(arg1, arg2); break; From 831a5a7fcbb3bfc36e8e7ed511817e8390344f87 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:23 +0300 Subject: [PATCH 168/208] bsd-user: Implement fork(2) and vfork(2) system calls. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-27-kariem.taha2.7@gmail.com> --- bsd-user/freebsd/os-proc.h | 34 ++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 8 ++++++++ 2 files changed, 42 insertions(+) diff --git a/bsd-user/freebsd/os-proc.h b/bsd-user/freebsd/os-proc.h index 42bdd61904b3..7b2e6a9f7965 100644 --- a/bsd-user/freebsd/os-proc.h +++ b/bsd-user/freebsd/os-proc.h @@ -185,4 +185,38 @@ static inline abi_long do_freebsd___setugid(abi_long arg1) return -TARGET_ENOSYS; } +/* fork(2) */ +static inline abi_long do_freebsd_fork(void *cpu_env) +{ + abi_long ret; + abi_ulong child_flag; + + fork_start(); + ret = fork(); + if (ret == 0) { + /* child */ + child_flag = 1; + target_cpu_clone_regs(cpu_env, 0); + } else { + /* parent */ + child_flag = 0; + } + + /* + * The fork system call sets a child flag in the second return + * value: 0 for parent process, 1 for child process. + */ + set_second_rval(cpu_env, child_flag); + + fork_end(child_flag); + + return ret; +} + +/* vfork(2) */ +static inline abi_long do_freebsd_vfork(void *cpu_env) +{ + return do_freebsd_fork(cpu_env); +} + #endif /* BSD_USER_FREEBSD_OS_PROC_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 99af0f6b156f..cb9425c9bab6 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -226,6 +226,14 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, /* * process system calls */ + case TARGET_FREEBSD_NR_fork: /* fork(2) */ + ret = do_freebsd_fork(cpu_env); + break; + + case TARGET_FREEBSD_NR_vfork: /* vfork(2) */ + ret = do_freebsd_vfork(cpu_env); + break; + case TARGET_FREEBSD_NR_execve: /* execve(2) */ ret = do_freebsd_execve(arg1, arg2, arg3); break; From 510eecbc86e1aa93c17e9e0a3acced366b0258e1 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:24 +0300 Subject: [PATCH 169/208] bsd-user: Implement rfork(2) system call. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-28-kariem.taha2.7@gmail.com> --- bsd-user/freebsd/os-proc.h | 39 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ 2 files changed, 43 insertions(+) diff --git a/bsd-user/freebsd/os-proc.h b/bsd-user/freebsd/os-proc.h index 7b2e6a9f7965..0a3cd0ef57c4 100644 --- a/bsd-user/freebsd/os-proc.h +++ b/bsd-user/freebsd/os-proc.h @@ -219,4 +219,43 @@ static inline abi_long do_freebsd_vfork(void *cpu_env) return do_freebsd_fork(cpu_env); } +/* rfork(2) */ +static inline abi_long do_freebsd_rfork(void *cpu_env, abi_long flags) +{ + abi_long ret; + abi_ulong child_flag; + + /* + * XXX We need to handle RFMEM here, as well. Neither are safe to execute + * as-is on x86 hosts because they'll split memory but not the stack, + * wreaking havoc on host architectures that use the stack to store the + * return address as both threads try to pop it off. Rejecting RFSPAWN + * entirely for now is ok, the only consumer at the moment is posix_spawn + * and it will fall back to classic vfork(2) if we return EINVAL. + */ + if ((flags & TARGET_RFSPAWN) != 0) { + return -TARGET_EINVAL; + } + fork_start(); + ret = rfork(flags); + if (ret == 0) { + /* child */ + child_flag = 1; + target_cpu_clone_regs(cpu_env, 0); + } else { + /* parent */ + child_flag = 0; + } + + /* + * The fork system call sets a child flag in the second return + * value: 0 for parent process, 1 for child process. + */ + set_second_rval(cpu_env, child_flag); + fork_end(child_flag); + + return ret; + +} + #endif /* BSD_USER_FREEBSD_OS_PROC_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index cb9425c9bab6..4c4e773d1d35 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -234,6 +234,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_freebsd_vfork(cpu_env); break; + case TARGET_FREEBSD_NR_rfork: /* rfork(2) */ + ret = do_freebsd_rfork(cpu_env, arg1); + break; + case TARGET_FREEBSD_NR_execve: /* execve(2) */ ret = do_freebsd_execve(arg1, arg2, arg3); break; From 6756ae283ac7fe43b8bbc1d8662dfe238f667032 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:24:25 +0300 Subject: [PATCH 170/208] bsd-user: Implement pdfork(2) system call. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Acked-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182425.3163-29-kariem.taha2.7@gmail.com> --- bsd-user/freebsd/os-proc.h | 32 ++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ 2 files changed, 36 insertions(+) diff --git a/bsd-user/freebsd/os-proc.h b/bsd-user/freebsd/os-proc.h index 0a3cd0ef57c4..d6418780344d 100644 --- a/bsd-user/freebsd/os-proc.h +++ b/bsd-user/freebsd/os-proc.h @@ -258,4 +258,36 @@ static inline abi_long do_freebsd_rfork(void *cpu_env, abi_long flags) } +/* pdfork(2) */ +static inline abi_long do_freebsd_pdfork(void *cpu_env, abi_ulong target_fdp, + abi_long flags) +{ + abi_long ret; + abi_ulong child_flag; + int fd; + + fork_start(); + ret = pdfork(&fd, flags); + if (ret == 0) { + /* child */ + child_flag = 1; + target_cpu_clone_regs(cpu_env, 0); + } else { + /* parent */ + child_flag = 0; + if (put_user_s32(fd, target_fdp)) { + return -TARGET_EFAULT; + } + } + + /* + * The fork system call sets a child flag in the second return + * value: 0 for parent process, 1 for child process. + */ + set_second_rval(cpu_env, child_flag); + fork_end(child_flag); + + return ret; +} + #endif /* BSD_USER_FREEBSD_OS_PROC_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 4c4e773d1d35..d04712f0a7ee 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -238,6 +238,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_freebsd_rfork(cpu_env, arg1); break; + case TARGET_FREEBSD_NR_pdfork: /* pdfork(2) */ + ret = do_freebsd_pdfork(cpu_env, arg1, arg2); + break; + case TARGET_FREEBSD_NR_execve: /* execve(2) */ ret = do_freebsd_execve(arg1, arg2, arg3); break; From 61a8f1100759a320940e8c53eaaefb37a4c603fb Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:26:47 +0300 Subject: [PATCH 171/208] bsd-user: Implement struct target_ipc_perm Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182709.4834-2-kariem.taha2.7@gmail.com> --- bsd-user/syscall_defs.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h index a3bc738ff891..0e54d7df6906 100644 --- a/bsd-user/syscall_defs.h +++ b/bsd-user/syscall_defs.h @@ -55,6 +55,23 @@ struct target_iovec { abi_long iov_len; /* Number of bytes */ }; +/* + * sys/ipc.h + */ +struct target_ipc_perm { + uint32_t cuid; /* creator user id */ + uint32_t cgid; /* creator group id */ + uint32_t uid; /* user id */ + uint32_t gid; /* group id */ + uint16_t mode; /* r/w permission */ + uint16_t seq; /* sequence # */ + abi_long key; /* user specified msg/sem/shm key */ +}; + +#define TARGET_IPC_RMID 0 /* remove identifier */ +#define TARGET_IPC_SET 1 /* set options */ +#define TARGET_IPC_STAT 2 /* get options */ + /* * sys/mman.h */ From 695cb9137f6c1b1bf940d303b2f26a46241056b8 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:26:48 +0300 Subject: [PATCH 172/208] bsd-user: Implement struct target_shmid_ds Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182709.4834-3-kariem.taha2.7@gmail.com> --- bsd-user/syscall_defs.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h index 0e54d7df6906..ff6928143338 100644 --- a/bsd-user/syscall_defs.h +++ b/bsd-user/syscall_defs.h @@ -72,6 +72,26 @@ struct target_ipc_perm { #define TARGET_IPC_SET 1 /* set options */ #define TARGET_IPC_STAT 2 /* get options */ +/* + * sys/shm.h + */ +struct target_shmid_ds { + struct target_ipc_perm shm_perm; /* peration permission structure */ + abi_ulong shm_segsz; /* size of segment in bytes */ + int32_t shm_lpid; /* process ID of last shared memory op */ + int32_t shm_cpid; /* process ID of creator */ + int32_t shm_nattch; /* number of current attaches */ + target_time_t shm_atime; /* time of last shmat() */ + target_time_t shm_dtime; /* time of last shmdt() */ + target_time_t shm_ctime; /* time of last change by shmctl() */ +}; + +#define N_BSD_SHM_REGIONS 32 +struct bsd_shm_regions { + abi_long start; + abi_long size; +}; + /* * sys/mman.h */ From 1d4c4026b15045e45de5c6f64e4b6322274680e7 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:26:49 +0300 Subject: [PATCH 173/208] bsd-user: Declarations for ipc_perm and shmid_ds conversion functions Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182709.4834-4-kariem.taha2.7@gmail.com> --- bsd-user/qemu-bsd.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/bsd-user/qemu-bsd.h b/bsd-user/qemu-bsd.h index b93a0b7fd5bf..ffc64bb244a7 100644 --- a/bsd-user/qemu-bsd.h +++ b/bsd-user/qemu-bsd.h @@ -22,6 +22,16 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* bsd-proc.c */ int target_to_host_resource(int code); @@ -35,4 +45,14 @@ int host_to_target_waitstatus(int status); void h2g_rusage(const struct rusage *rusage, struct target_freebsd_rusage *target_rusage); +/* bsd-mem.c */ +void target_to_host_ipc_perm__locked(struct ipc_perm *host_ip, + struct target_ipc_perm *target_ip); +void host_to_target_ipc_perm__locked(struct target_ipc_perm *target_ip, + struct ipc_perm *host_ip); +abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd, + abi_ulong target_addr); +abi_long host_to_target_shmid_ds(abi_ulong target_addr, + struct shmid_ds *host_sd); + #endif /* QEMU_BSD_H */ From 137d963cfb1c9f0d9e76a40229df2996809b746b Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:26:50 +0300 Subject: [PATCH 174/208] bsd-user: Introduce freebsd/os-misc.h to the source tree To preserve the copyright notice and help with the 'Author' info for subsequent changes to the file. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182709.4834-5-kariem.taha2.7@gmail.com> --- bsd-user/freebsd/os-misc.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 bsd-user/freebsd/os-misc.h diff --git a/bsd-user/freebsd/os-misc.h b/bsd-user/freebsd/os-misc.h new file mode 100644 index 000000000000..8436ccb2f7d8 --- /dev/null +++ b/bsd-user/freebsd/os-misc.h @@ -0,0 +1,28 @@ +/* + * miscellaneous FreeBSD system call shims + * + * Copyright (c) 2013-14 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef OS_MISC_H +#define OS_MISC_H + +#include +#include +#include + + +#endif /* OS_MISC_H */ From 0c3529888a427cefe248227423f7a89c8f665fab Mon Sep 17 00:00:00 2001 From: Karim Taha Date: Mon, 25 Sep 2023 21:26:51 +0300 Subject: [PATCH 175/208] bsd-user: Implement shm_open2(2) system call Signed-off-by: Kyle Evans Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-6-kariem.taha2.7@gmail.com> --- bsd-user/freebsd/os-misc.h | 46 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 22 ++++++++++++----- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/bsd-user/freebsd/os-misc.h b/bsd-user/freebsd/os-misc.h index 8436ccb2f7d8..d5e8b5484c83 100644 --- a/bsd-user/freebsd/os-misc.h +++ b/bsd-user/freebsd/os-misc.h @@ -24,5 +24,51 @@ #include #include +/* + * shm_open2 isn't exported, but the __sys_ alias is. We can use either for the + * static version, but to dynamically link we have to use the sys version. + */ +int __sys_shm_open2(const char *path, int flags, mode_t mode, int shmflags, + const char *); + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 +/* shm_open2(2) */ +static inline abi_long do_freebsd_shm_open2(abi_ulong pathptr, abi_ulong flags, + abi_long mode, abi_ulong shmflags, abi_ulong nameptr) +{ + int ret; + void *uname, *upath; + + if (pathptr == (uintptr_t)SHM_ANON) { + upath = SHM_ANON; + } else { + upath = lock_user_string(pathptr); + if (upath == NULL) { + return -TARGET_EFAULT; + } + } + + uname = NULL; + if (nameptr != 0) { + uname = lock_user_string(nameptr); + if (uname == NULL) { + unlock_user(upath, pathptr, 0); + return -TARGET_EFAULT; + } + } + ret = get_errno(__sys_shm_open2(upath, + target_to_host_bitmask(flags, fcntl_flags_tbl), mode, + target_to_host_bitmask(shmflags, shmflag_flags_tbl), uname)); + + if (upath != SHM_ANON) { + unlock_user(upath, pathptr, 0); + } + if (uname != NULL) { + unlock_user(uname, nameptr, 0); + } + return ret; +} +#endif /* __FreeBSD_version >= 1300048 */ + #endif /* OS_MISC_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index d04712f0a7ee..122e186b5019 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -33,18 +33,14 @@ #include "signal-common.h" #include "user/syscall-trace.h" +/* BSD independent syscall shims */ #include "bsd-file.h" #include "bsd-proc.h" /* BSD dependent syscall shims */ #include "os-stat.h" #include "os-proc.h" - -/* used in os-proc */ -safe_syscall4(pid_t, wait4, pid_t, wpid, int *, status, int, options, - struct rusage *, rusage); -safe_syscall6(pid_t, wait6, idtype_t, idtype, id_t, id, int *, status, int, - options, struct __wrusage *, wrusage, siginfo_t *, infop); +#include "os-misc.h" /* I/O */ safe_syscall3(int, open, const char *, path, int, flags, mode_t, mode); @@ -65,6 +61,12 @@ safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt); safe_syscall4(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt, off_t, offset); +/* used in os-proc */ +safe_syscall4(pid_t, wait4, pid_t, wpid, int *, status, int, options, + struct rusage *, rusage); +safe_syscall6(pid_t, wait6, idtype_t, idtype, id_t, id, int *, status, int, + options, struct __wrusage *, wrusage, siginfo_t *, infop); + void target_set_brk(abi_ulong new_brk) { } @@ -796,6 +798,14 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_freebsd_fcntl(arg1, arg2, arg3); break; + /* + * Memory management system calls. + */ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 + case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */ + ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5); + break; +#endif /* * sys{ctl, arch, call} From 182ea728e06a09e6ceaa9d62a279e883459d36dd Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 25 Sep 2023 21:26:52 +0300 Subject: [PATCH 176/208] bsd-user: Implement shm_rename(2) system call Signed-off-by: Kyle Evans Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182709.4834-7-kariem.taha2.7@gmail.com> --- bsd-user/freebsd/os-misc.h | 24 ++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 6 ++++++ 2 files changed, 30 insertions(+) diff --git a/bsd-user/freebsd/os-misc.h b/bsd-user/freebsd/os-misc.h index d5e8b5484c83..71145764a4d1 100644 --- a/bsd-user/freebsd/os-misc.h +++ b/bsd-user/freebsd/os-misc.h @@ -70,5 +70,29 @@ static inline abi_long do_freebsd_shm_open2(abi_ulong pathptr, abi_ulong flags, } #endif /* __FreeBSD_version >= 1300048 */ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 1300049 +/* shm_rename(2) */ +static inline abi_long do_freebsd_shm_rename(abi_ulong fromptr, abi_ulong toptr, + abi_ulong flags) +{ + int ret; + void *ufrom, *uto; + + ufrom = lock_user_string(fromptr); + if (ufrom == NULL) { + return -TARGET_EFAULT; + } + uto = lock_user_string(toptr); + if (uto == NULL) { + unlock_user(ufrom, fromptr, 0); + return -TARGET_EFAULT; + } + ret = get_errno(shm_rename(ufrom, uto, flags)); + unlock_user(ufrom, fromptr, 0); + unlock_user(uto, toptr, 0); + + return ret; +} +#endif /* __FreeBSD_version >= 1300049 */ #endif /* OS_MISC_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 122e186b5019..5fb42b2c2182 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -807,6 +807,12 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, break; #endif +#if defined(__FreeBSD_version) && __FreeBSD_version >= 1300049 + case TARGET_FREEBSD_NR_shm_rename: /* shm_rename(2) */ + ret = do_freebsd_shm_rename(arg1, arg2, arg3); + break; +#endif + /* * sys{ctl, arch, call} */ From dde5f40dc38d61e80a91c482d9faf45eacdceed8 Mon Sep 17 00:00:00 2001 From: Karim Taha Date: Mon, 25 Sep 2023 21:26:53 +0300 Subject: [PATCH 177/208] bsd-user: Add bsd-mem.c to meson.build Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182709.4834-8-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.c | 0 bsd-user/meson.build | 1 + 2 files changed, 1 insertion(+) create mode 100644 bsd-user/bsd-mem.c diff --git a/bsd-user/bsd-mem.c b/bsd-user/bsd-mem.c new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bsd-user/meson.build b/bsd-user/meson.build index b97fce14722f..c6bfd3b2b539 100644 --- a/bsd-user/meson.build +++ b/bsd-user/meson.build @@ -7,6 +7,7 @@ bsd_user_ss = ss.source_set() common_user_inc += include_directories('include') bsd_user_ss.add(files( + 'bsd-mem.c', 'bsd-proc.c', 'bsdload.c', 'elfload.c', From c9cdf0a5ecfd16176e48a8cec6fc4a22d9d7b229 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:26:54 +0300 Subject: [PATCH 178/208] bsd-user: Implement target_set_brk function in bsd-mem.c instead of os-syscall.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The definitions and variables names matches the corresponding ones in linux-user/syscall.c, for making later implementation of do_obreak easier Co-authored-by: Mikaël Urankar Signed-off-by: Mikaël Urankar Signed-off-by: Karim Taha Reviewed-by: Warner Losh Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-9-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.c | 32 ++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 4 ---- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/bsd-user/bsd-mem.c b/bsd-user/bsd-mem.c index e69de29bb2d1..8834ab2e5889 100644 --- a/bsd-user/bsd-mem.c +++ b/bsd-user/bsd-mem.c @@ -0,0 +1,32 @@ +/* + * memory management system conversion routines + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +#include "qemu/osdep.h" +#include "qemu.h" +#include "qemu-bsd.h" + +struct bsd_shm_regions bsd_shm_regions[N_BSD_SHM_REGIONS]; + +abi_ulong target_brk; +abi_ulong initial_target_brk; + +void target_set_brk(abi_ulong new_brk) +{ + target_brk = TARGET_PAGE_ALIGN(new_brk); + initial_target_brk = target_brk; +} diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 5fb42b2c2182..c9d34b59bbec 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -67,10 +67,6 @@ safe_syscall4(pid_t, wait4, pid_t, wpid, int *, status, int, options, safe_syscall6(pid_t, wait6, idtype_t, idtype, id_t, id, int *, status, int, options, struct __wrusage *, wrusage, siginfo_t *, infop); -void target_set_brk(abi_ulong new_brk) -{ -} - /* * errno conversion. */ From 86fbb4436bd09c5006c1f07d4cb007b2e91b595a Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:26:55 +0300 Subject: [PATCH 179/208] bsd-user: Implement ipc_perm conversion between host and target. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-10-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/bsd-user/bsd-mem.c b/bsd-user/bsd-mem.c index 8834ab2e5889..46cda8eb5ceb 100644 --- a/bsd-user/bsd-mem.c +++ b/bsd-user/bsd-mem.c @@ -30,3 +30,28 @@ void target_set_brk(abi_ulong new_brk) target_brk = TARGET_PAGE_ALIGN(new_brk); initial_target_brk = target_brk; } + +void target_to_host_ipc_perm__locked(struct ipc_perm *host_ip, + struct target_ipc_perm *target_ip) +{ + __get_user(host_ip->cuid, &target_ip->cuid); + __get_user(host_ip->cgid, &target_ip->cgid); + __get_user(host_ip->uid, &target_ip->uid); + __get_user(host_ip->gid, &target_ip->gid); + __get_user(host_ip->mode, &target_ip->mode); + __get_user(host_ip->seq, &target_ip->seq); + __get_user(host_ip->key, &target_ip->key); +} + +void host_to_target_ipc_perm__locked(struct target_ipc_perm *target_ip, + struct ipc_perm *host_ip) +{ + __put_user(host_ip->cuid, &target_ip->cuid); + __put_user(host_ip->cgid, &target_ip->cgid); + __put_user(host_ip->uid, &target_ip->uid); + __put_user(host_ip->gid, &target_ip->gid); + __put_user(host_ip->mode, &target_ip->mode); + __put_user(host_ip->seq, &target_ip->seq); + __put_user(host_ip->key, &target_ip->key); +} + From bd2b73182f5a793c1b226a2846c847faaa7b3e9d Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:26:56 +0300 Subject: [PATCH 180/208] bsd-user: Implement shmid_ds conversion between host and target. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-11-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/bsd-user/bsd-mem.c b/bsd-user/bsd-mem.c index 46cda8eb5ceb..2ab1334b7003 100644 --- a/bsd-user/bsd-mem.c +++ b/bsd-user/bsd-mem.c @@ -43,6 +43,30 @@ void target_to_host_ipc_perm__locked(struct ipc_perm *host_ip, __get_user(host_ip->key, &target_ip->key); } +abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd, + abi_ulong target_addr) +{ + struct target_shmid_ds *target_sd; + + if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) { + return -TARGET_EFAULT; + } + + target_to_host_ipc_perm__locked(&(host_sd->shm_perm), + &(target_sd->shm_perm)); + + __get_user(host_sd->shm_segsz, &target_sd->shm_segsz); + __get_user(host_sd->shm_lpid, &target_sd->shm_lpid); + __get_user(host_sd->shm_cpid, &target_sd->shm_cpid); + __get_user(host_sd->shm_nattch, &target_sd->shm_nattch); + __get_user(host_sd->shm_atime, &target_sd->shm_atime); + __get_user(host_sd->shm_dtime, &target_sd->shm_dtime); + __get_user(host_sd->shm_ctime, &target_sd->shm_ctime); + unlock_user_struct(target_sd, target_addr, 0); + + return 0; +} + void host_to_target_ipc_perm__locked(struct target_ipc_perm *target_ip, struct ipc_perm *host_ip) { @@ -55,3 +79,26 @@ void host_to_target_ipc_perm__locked(struct target_ipc_perm *target_ip, __put_user(host_ip->key, &target_ip->key); } +abi_long host_to_target_shmid_ds(abi_ulong target_addr, + struct shmid_ds *host_sd) +{ + struct target_shmid_ds *target_sd; + + if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) { + return -TARGET_EFAULT; + } + + host_to_target_ipc_perm__locked(&(target_sd->shm_perm), + &(host_sd->shm_perm)); + + __put_user(host_sd->shm_segsz, &target_sd->shm_segsz); + __put_user(host_sd->shm_lpid, &target_sd->shm_lpid); + __put_user(host_sd->shm_cpid, &target_sd->shm_cpid); + __put_user(host_sd->shm_nattch, &target_sd->shm_nattch); + __put_user(host_sd->shm_atime, &target_sd->shm_atime); + __put_user(host_sd->shm_dtime, &target_sd->shm_dtime); + __put_user(host_sd->shm_ctime, &target_sd->shm_ctime); + unlock_user_struct(target_sd, target_addr, 1); + + return 0; +} From 6765e988e12825e9464a10b6451aeb25b29bfbc3 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:26:57 +0300 Subject: [PATCH 181/208] bsd-user: Introduce bsd-mem.h to the source tree Preserve the copyright notice and help with the 'Author' info for subsequent changes to the file. Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-12-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 64 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 1 + 2 files changed, 65 insertions(+) create mode 100644 bsd-user/bsd-mem.h diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h new file mode 100644 index 000000000000..d865e0807d85 --- /dev/null +++ b/bsd-user/bsd-mem.h @@ -0,0 +1,64 @@ +/* + * memory management system call shims and definitions + * + * Copyright (c) 2013-15 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef BSD_USER_BSD_MEM_H +#define BSD_USER_BSD_MEM_H + +#include +#include +#include +#include +#include + +#include "qemu-bsd.h" + +extern struct bsd_shm_regions bsd_shm_regions[]; +extern abi_ulong target_brk; +extern abi_ulong initial_target_brk; + +#endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index c9d34b59bbec..7887ad4c0c63 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -35,6 +35,7 @@ /* BSD independent syscall shims */ #include "bsd-file.h" +#include "bsd-mem.h" #include "bsd-proc.h" /* BSD dependent syscall shims */ From 87dcb4ad485424dcbfedbc7a298279e8738f1a40 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:26:58 +0300 Subject: [PATCH 182/208] bsd-user: Implement mmap(2) and munmap(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-13-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 20 ++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 9 +++++++++ 2 files changed, 29 insertions(+) diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index d865e0807d85..76b504f70c57 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -61,4 +61,24 @@ extern struct bsd_shm_regions bsd_shm_regions[]; extern abi_ulong target_brk; extern abi_ulong initial_target_brk; +/* mmap(2) */ +static inline abi_long do_bsd_mmap(void *cpu_env, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6, abi_long arg7, + abi_long arg8) +{ + if (regpairs_aligned(cpu_env) != 0) { + arg6 = arg7; + arg7 = arg8; + } + return get_errno(target_mmap(arg1, arg2, arg3, + target_to_host_bitmask(arg4, mmap_flags_tbl), + arg5, target_arg64(arg6, arg7))); +} + +/* munmap(2) */ +static inline abi_long do_bsd_munmap(abi_long arg1, abi_long arg2) +{ + return get_errno(target_munmap(arg1, arg2)); +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 7887ad4c0c63..b03837d032ab 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -798,6 +798,15 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, /* * Memory management system calls. */ + case TARGET_FREEBSD_NR_mmap: /* mmap(2) */ + ret = do_bsd_mmap(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, + arg8); + break; + + case TARGET_FREEBSD_NR_munmap: /* munmap(2) */ + ret = do_bsd_munmap(arg1, arg2); + break; + #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */ ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5); From ecbe22494d970b7811a1764d2f98e083b02f73d0 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:26:59 +0300 Subject: [PATCH 183/208] bsd-user: Implement mprotect(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Reviewed-by: Warner Losh Message-Id: <20230925182709.4834-14-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 7 +++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index 76b504f70c57..0f9e4a1d4bef 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -81,4 +81,11 @@ static inline abi_long do_bsd_munmap(abi_long arg1, abi_long arg2) return get_errno(target_munmap(arg1, arg2)); } +/* mprotect(2) */ +static inline abi_long do_bsd_mprotect(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + return get_errno(target_mprotect(arg1, arg2, arg3)); +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index b03837d032ab..2d8f1a953b28 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -807,6 +807,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_munmap(arg1, arg2); break; + case TARGET_FREEBSD_NR_mprotect: /* mprotect(2) */ + ret = do_bsd_mprotect(arg1, arg2, arg3); + break; + #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */ ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5); From f28a1e4bab4cfdd067bde3d958529575aa8e8f6b Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:00 +0300 Subject: [PATCH 184/208] bsd-user: Implement msync(2) Co-authored-by: Kyle Evans Signed-off-by: Stacey Son Signed-off-by: Kyle Evans Signed-off-by: Karim Taha Reviewed-by: Warner Losh Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-15-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 11 +++++++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index 0f9e4a1d4bef..5e885823a797 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -88,4 +88,15 @@ static inline abi_long do_bsd_mprotect(abi_long arg1, abi_long arg2, return get_errno(target_mprotect(arg1, arg2, arg3)); } +/* msync(2) */ +static inline abi_long do_bsd_msync(abi_long addr, abi_long len, abi_long flags) +{ + if (!guest_range_valid_untagged(addr, len)) { + /* It seems odd, but POSIX wants this to be ENOMEM */ + return -TARGET_ENOMEM; + } + + return get_errno(msync(g2h_untagged(addr), len, flags)); +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 2d8f1a953b28..2525e0bc3160 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -811,6 +811,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_mprotect(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_msync: /* msync(2) */ + ret = do_bsd_msync(arg1, arg2, arg3); + break; + #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */ ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5); From 0a49ef02a643864a9c6a36ebaf452e0d30c96b0b Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:01 +0300 Subject: [PATCH 185/208] bsd-user: Implement mlock(2), munlock(2), mlockall(2), munlockall(2), minherit(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-16-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 37 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 20 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index 5e885823a797..16c22593bfdf 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -99,4 +99,41 @@ static inline abi_long do_bsd_msync(abi_long addr, abi_long len, abi_long flags) return get_errno(msync(g2h_untagged(addr), len, flags)); } +/* mlock(2) */ +static inline abi_long do_bsd_mlock(abi_long arg1, abi_long arg2) +{ + if (!guest_range_valid_untagged(arg1, arg2)) { + return -TARGET_EINVAL; + } + return get_errno(mlock(g2h_untagged(arg1), arg2)); +} + +/* munlock(2) */ +static inline abi_long do_bsd_munlock(abi_long arg1, abi_long arg2) +{ + if (!guest_range_valid_untagged(arg1, arg2)) { + return -TARGET_EINVAL; + } + return get_errno(munlock(g2h_untagged(arg1), arg2)); +} + +/* mlockall(2) */ +static inline abi_long do_bsd_mlockall(abi_long arg1) +{ + return get_errno(mlockall(arg1)); +} + +/* munlockall(2) */ +static inline abi_long do_bsd_munlockall(void) +{ + return get_errno(munlockall()); +} + +/* minherit(2) */ +static inline abi_long do_bsd_minherit(abi_long addr, abi_long len, + abi_long inherit) +{ + return get_errno(minherit(g2h_untagged(addr), len, inherit)); +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 2525e0bc3160..7a7ae26793fb 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -815,6 +815,26 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_msync(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_mlock: /* mlock(2) */ + ret = do_bsd_mlock(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_munlock: /* munlock(2) */ + ret = do_bsd_munlock(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_mlockall: /* mlockall(2) */ + ret = do_bsd_mlockall(arg1); + break; + + case TARGET_FREEBSD_NR_munlockall: /* munlockall(2) */ + ret = do_bsd_munlockall(); + break; + + case TARGET_FREEBSD_NR_minherit: /* minherit(2) */ + ret = do_bsd_minherit(arg1, arg2, arg3); + break; + #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */ ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5); From 0c1ced42c84bdd8beeef6c40dff8d143cf409f15 Mon Sep 17 00:00:00 2001 From: Karim Taha Date: Mon, 25 Sep 2023 21:27:02 +0300 Subject: [PATCH 186/208] bsd-user: Implment madvise(2) to match the linux-user implementation. Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-17-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 53 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 4 +++ bsd-user/syscall_defs.h | 2 ++ 3 files changed, 59 insertions(+) diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index 16c22593bfdf..b00ab3aed8ed 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -129,6 +129,59 @@ static inline abi_long do_bsd_munlockall(void) return get_errno(munlockall()); } +/* madvise(2) */ +static inline abi_long do_bsd_madvise(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + abi_ulong len; + int ret = 0; + abi_long start = arg1; + abi_long len_in = arg2; + abi_long advice = arg3; + + if (start & ~TARGET_PAGE_MASK) { + return -TARGET_EINVAL; + } + if (len_in == 0) { + return 0; + } + len = TARGET_PAGE_ALIGN(len_in); + if (len == 0 || !guest_range_valid_untagged(start, len)) { + return -TARGET_EINVAL; + } + + /* + * Most advice values are hints, so ignoring and returning success is ok. + * + * However, some advice values such as MADV_DONTNEED, are not hints and + * need to be emulated. + * + * A straight passthrough for those may not be safe because qemu sometimes + * turns private file-backed mappings into anonymous mappings. + * If all guest pages have PAGE_PASSTHROUGH set, mappings have the + * same semantics for the host as for the guest. + * + * MADV_DONTNEED is passed through, if possible. + * If passthrough isn't possible, we nevertheless (wrongly!) return + * success, which is broken but some userspace programs fail to work + * otherwise. Completely implementing such emulation is quite complicated + * though. + */ + mmap_lock(); + switch (advice) { + case MADV_DONTNEED: + if (page_check_range(start, len, PAGE_PASSTHROUGH)) { + ret = get_errno(madvise(g2h_untagged(start), len, advice)); + if (ret == 0) { + page_reset_target_data(start, start + len - 1); + } + } + } + mmap_unlock(); + + return ret; +} + /* minherit(2) */ static inline abi_long do_bsd_minherit(abi_long addr, abi_long len, abi_long inherit) diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 7a7ae26793fb..b8c44cea0ff6 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -831,6 +831,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_munlockall(); break; + case TARGET_FREEBSD_NR_madvise: /* madvise(2) */ + ret = do_bsd_madvise(arg1, arg2, arg3); + break; + case TARGET_FREEBSD_NR_minherit: /* minherit(2) */ ret = do_bsd_minherit(arg1, arg2, arg3); break; diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h index ff6928143338..52f84d5dd173 100644 --- a/bsd-user/syscall_defs.h +++ b/bsd-user/syscall_defs.h @@ -95,6 +95,8 @@ struct bsd_shm_regions { /* * sys/mman.h */ +#define TARGET_MADV_DONTNEED 4 /* dont need these pages */ + #define TARGET_FREEBSD_MAP_RESERVED0080 0x0080 /* previously misimplemented */ /* MAP_INHERIT */ #define TARGET_FREEBSD_MAP_RESERVED0100 0x0100 /* previously unimplemented */ From 83b045ad4e0106836963185ed696991883104359 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:03 +0300 Subject: [PATCH 187/208] bsd-user: Implement mincore(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-18-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 23 +++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index b00ab3aed8ed..0c8d96d9a432 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -189,4 +189,27 @@ static inline abi_long do_bsd_minherit(abi_long addr, abi_long len, return get_errno(minherit(g2h_untagged(addr), len, inherit)); } +/* mincore(2) */ +static inline abi_long do_bsd_mincore(abi_ulong target_addr, abi_ulong len, + abi_ulong target_vec) +{ + abi_long ret; + void *p; + abi_ulong vec_len = DIV_ROUND_UP(len, TARGET_PAGE_SIZE); + + if (!guest_range_valid_untagged(target_addr, len) + || !page_check_range(target_addr, len, PAGE_VALID)) { + return -TARGET_EFAULT; + } + + p = lock_user(VERIFY_WRITE, target_vec, vec_len, 0); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(mincore(g2h_untagged(target_addr), len, p)); + unlock_user(p, target_vec, vec_len); + + return ret; +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index b8c44cea0ff6..f054241cd628 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -839,6 +839,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_minherit(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_mincore: /* mincore(2) */ + ret = do_bsd_mincore(arg1, arg2, arg3); + break; + #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */ ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5); From a99d74034754b1d8735d814cf17db6bf0eb4bfd1 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:04 +0300 Subject: [PATCH 188/208] bsd-user: Implement do_obreak function Match linux-user, by manually applying the following commits, in order: d28b3c90cfad1a7e211ae2bce36ecb9071086129 linux-user: Make sure initial brk(0) is page-aligned 15ad98536ad9410fb32ddf1ff09389b677643faa linux-user: Fix qemu brk() to not zero bytes on current page dfe49864afb06e7e452a4366051697bc4fcfc1a5 linux-user: Prohibit brk() to to shrink below initial heap address eac78a4b0b7da4de2c0a297f4d528ca9cc6256a3 linux-user: Fix signed math overflow in brk() syscall c6cc059eca18d9f6e4e26bb8b6d1135ddb35d81a linux-user: Do not call get_errno() in do_brk() e69e032d1a8ee8d754ca119009a3c2c997f8bb30 linux-user: Use MAP_FIXED_NOREPLACE for do_brk() cb9d5d1fda0bc2312fc0c779b4ea1d7bf826f31f linux-user: Do nothing if too small brk is specified 2aea137a425a87b930a33590177b04368fd7cc12 linux-user: Do not align brk with host page size Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-19-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 45 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 7 ++++++ 2 files changed, 52 insertions(+) diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index 0c8d96d9a432..b296c5c6f0ac 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -212,4 +212,49 @@ static inline abi_long do_bsd_mincore(abi_ulong target_addr, abi_ulong len, return ret; } +/* do_brk() must return target values and target errnos. */ +static inline abi_long do_obreak(abi_ulong brk_val) +{ + abi_long mapped_addr; + abi_ulong new_brk; + abi_ulong old_brk; + + /* brk pointers are always untagged */ + + /* do not allow to shrink below initial brk value */ + if (brk_val < initial_target_brk) { + return target_brk; + } + + new_brk = TARGET_PAGE_ALIGN(brk_val); + old_brk = TARGET_PAGE_ALIGN(target_brk); + + /* new and old target_brk might be on the same page */ + if (new_brk == old_brk) { + target_brk = brk_val; + return target_brk; + } + + /* Release heap if necesary */ + if (new_brk < old_brk) { + target_munmap(new_brk, old_brk - new_brk); + + target_brk = brk_val; + return target_brk; + } + + mapped_addr = target_mmap(old_brk, new_brk - old_brk, + PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_EXCL | MAP_ANON | MAP_PRIVATE, + -1, 0); + + if (mapped_addr == old_brk) { + target_brk = brk_val; + return target_brk; + } + + /* For everything else, return the previous break. */ + return target_brk; +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index f054241cd628..92793ab1fb3d 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -855,6 +855,13 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, break; #endif + /* + * Misc + */ + case TARGET_FREEBSD_NR_break: + ret = do_obreak(arg1); + break; + /* * sys{ctl, arch, call} */ From 4f0be683e399e7685608b83240da099ea45d84e6 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:05 +0300 Subject: [PATCH 189/208] bsd-user: Implement shm_open(2) Co-authored-by: Kyle Evans Signed-off-by: Stacey Son Signed-off-by: Kyle Evans Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-20-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 25 +++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ 2 files changed, 29 insertions(+) diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index b296c5c6f0ac..f8dc943c2345 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -257,4 +257,29 @@ static inline abi_long do_obreak(abi_ulong brk_val) return target_brk; } +/* shm_open(2) */ +static inline abi_long do_bsd_shm_open(abi_ulong arg1, abi_long arg2, + abi_long arg3) +{ + int ret; + void *p; + + if (arg1 == (uintptr_t)SHM_ANON) { + p = SHM_ANON; + } else { + p = lock_user_string(arg1); + if (p == NULL) { + return -TARGET_EFAULT; + } + } + ret = get_errno(shm_open(p, target_to_host_bitmask(arg2, fcntl_flags_tbl), + arg3)); + + if (p != SHM_ANON) { + unlock_user(p, arg1, 0); + } + + return ret; +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 92793ab1fb3d..0d4c3118f0dc 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -843,6 +843,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_mincore(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_freebsd12_shm_open: /* shm_open(2) */ + ret = do_bsd_shm_open(arg1, arg2, arg3); + break; + #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 case TARGET_FREEBSD_NR_shm_open2: /* shm_open2(2) */ ret = do_freebsd_shm_open2(arg1, arg2, arg3, arg4, arg5); From 9d14db15b121c81a008098c46053d98cd6a0da6b Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:06 +0300 Subject: [PATCH 190/208] bsd-user: Implement shm_unlink(2) and shmget(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Warner Losh Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-21-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 23 +++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 8 ++++++++ 2 files changed, 31 insertions(+) diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index f8dc943c2345..c362cc07a307 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -282,4 +282,27 @@ static inline abi_long do_bsd_shm_open(abi_ulong arg1, abi_long arg2, return ret; } +/* shm_unlink(2) */ +static inline abi_long do_bsd_shm_unlink(abi_ulong arg1) +{ + int ret; + void *p; + + p = lock_user_string(arg1); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(shm_unlink(p)); /* XXX path(p)? */ + unlock_user(p, arg1, 0); + + return ret; +} + +/* shmget(2) */ +static inline abi_long do_bsd_shmget(abi_long arg1, abi_ulong arg2, + abi_long arg3) +{ + return get_errno(shmget(arg1, arg2, arg3)); +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 0d4c3118f0dc..4f67677eb92e 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -859,6 +859,14 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, break; #endif + case TARGET_FREEBSD_NR_shm_unlink: /* shm_unlink(2) */ + ret = do_bsd_shm_unlink(arg1); + break; + + case TARGET_FREEBSD_NR_shmget: /* shmget(2) */ + ret = do_bsd_shmget(arg1, arg2, arg3); + break; + /* * Misc */ From f9bbe3cf28ae7157724a364da6f4a7231f2fdfb3 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:07 +0300 Subject: [PATCH 191/208] bsd-user: Implement shmctl(2) Signed-off-by: Stacey Son Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-22-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 39 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 4 ++++ 2 files changed, 43 insertions(+) diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index c362cc07a307..b82f3eaa2531 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -305,4 +305,43 @@ static inline abi_long do_bsd_shmget(abi_long arg1, abi_ulong arg2, return get_errno(shmget(arg1, arg2, arg3)); } +/* shmctl(2) */ +static inline abi_long do_bsd_shmctl(abi_long shmid, abi_long cmd, + abi_ulong buff) +{ + struct shmid_ds dsarg; + abi_long ret = -TARGET_EINVAL; + + cmd &= 0xff; + + switch (cmd) { + case IPC_STAT: + if (target_to_host_shmid_ds(&dsarg, buff)) { + return -TARGET_EFAULT; + } + ret = get_errno(shmctl(shmid, cmd, &dsarg)); + if (host_to_target_shmid_ds(buff, &dsarg)) { + return -TARGET_EFAULT; + } + break; + + case IPC_SET: + if (target_to_host_shmid_ds(&dsarg, buff)) { + return -TARGET_EFAULT; + } + ret = get_errno(shmctl(shmid, cmd, &dsarg)); + break; + + case IPC_RMID: + ret = get_errno(shmctl(shmid, cmd, NULL)); + break; + + default: + ret = -TARGET_EINVAL; + break; + } + + return ret; +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 4f67677eb92e..0512d41db7c1 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -867,6 +867,10 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_shmget(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_shmctl: /* shmctl(2) */ + ret = do_bsd_shmctl(arg1, arg2, arg3); + break; + /* * Misc */ From 4e00b7d85d0dcc2064c68168163d3a411e32798f Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 25 Sep 2023 21:27:08 +0300 Subject: [PATCH 192/208] bsd-user: Implement shmat(2) and shmdt(2) Use `WITH_MMAP_LOCK_GUARD` instead of mmap_lock() and mmap_unlock(), to match linux-user implementation, according to the following commits: 69fa2708a216df715ba5102a0f98468b540a464e linux-user: Use WITH_MMAP_LOCK_GUARD in target_{shmat,shmdt} ceda5688b650646248f269a992c06b11148c5759 linux-user: Fix shmdt Signed-off-by: Stacey Son Signed-off-by: Karim Taha Message-Id: <20230925182709.4834-23-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 87 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 8 ++++ bsd-user/mmap.c | 2 +- bsd-user/qemu.h | 1 + 4 files changed, 97 insertions(+), 1 deletion(-) diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index b82f3eaa2531..c512a4e37569 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -344,4 +344,91 @@ static inline abi_long do_bsd_shmctl(abi_long shmid, abi_long cmd, return ret; } +/* shmat(2) */ +static inline abi_long do_bsd_shmat(int shmid, abi_ulong shmaddr, int shmflg) +{ + abi_ulong raddr; + abi_long ret; + struct shmid_ds shm_info; + + /* Find out the length of the shared memory segment. */ + ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info)); + if (is_error(ret)) { + /* Can't get the length */ + return ret; + } + + if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) { + return -TARGET_EINVAL; + } + + WITH_MMAP_LOCK_GUARD() { + void *host_raddr; + + if (shmaddr) { + host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg); + } else { + abi_ulong mmap_start; + + mmap_start = mmap_find_vma(0, shm_info.shm_segsz); + + if (mmap_start == -1) { + return -TARGET_ENOMEM; + } + host_raddr = shmat(shmid, g2h_untagged(mmap_start), + shmflg | SHM_REMAP); + } + + if (host_raddr == (void *)-1) { + return get_errno(-1); + } + raddr = h2g(host_raddr); + + page_set_flags(raddr, raddr + shm_info.shm_segsz - 1, + PAGE_VALID | PAGE_RESET | PAGE_READ | + (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE)); + + for (int i = 0; i < N_BSD_SHM_REGIONS; i++) { + if (bsd_shm_regions[i].start == 0) { + bsd_shm_regions[i].start = raddr; + bsd_shm_regions[i].size = shm_info.shm_segsz; + break; + } + } + } + + return raddr; +} + +/* shmdt(2) */ +static inline abi_long do_bsd_shmdt(abi_ulong shmaddr) +{ + abi_long ret; + + WITH_MMAP_LOCK_GUARD() { + int i; + + for (i = 0; i < N_BSD_SHM_REGIONS; ++i) { + if (bsd_shm_regions[i].start == shmaddr) { + break; + } + } + + if (i == N_BSD_SHM_REGIONS) { + return -TARGET_EINVAL; + } + + ret = get_errno(shmdt(g2h_untagged(shmaddr))); + if (ret == 0) { + abi_ulong size = bsd_shm_regions[i].size; + + bsd_shm_regions[i].start = 0; + page_set_flags(shmaddr, shmaddr + size - 1, 0); + mmap_reserve(shmaddr, size); + } + } + + return ret; +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 0512d41db7c1..39e66312da1a 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -871,6 +871,14 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_shmctl(arg1, arg2, arg3); break; + case TARGET_FREEBSD_NR_shmat: /* shmat(2) */ + ret = do_bsd_shmat(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_shmdt: /* shmdt(2) */ + ret = do_bsd_shmdt(arg1); + break; + /* * Misc */ diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c index 8e148a2ea3e2..3ef11b28079b 100644 --- a/bsd-user/mmap.c +++ b/bsd-user/mmap.c @@ -636,7 +636,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, return -1; } -static void mmap_reserve(abi_ulong start, abi_ulong size) +void mmap_reserve(abi_ulong start, abi_ulong size) { abi_ulong real_start; abi_ulong real_end; diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index 6047805ae387..dc842fffa7d3 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -233,6 +233,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, int target_msync(abi_ulong start, abi_ulong len, int flags); extern abi_ulong mmap_next_start; abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size); +void mmap_reserve(abi_ulong start, abi_ulong size); void TSA_NO_TSA mmap_fork_start(void); void TSA_NO_TSA mmap_fork_end(int child); From dfa1d915756b2d9d22946cbd7d2587f30cdcb7a3 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Mon, 25 Sep 2023 21:27:09 +0300 Subject: [PATCH 193/208] bsd-user: Add stubs for vadvise(), sbrk() and sstk() The above system calls are not supported by qemu. Signed-off-by: Warner Losh Signed-off-by: Karim Taha Reviewed-by: Richard Henderson Message-Id: <20230925182709.4834-24-kariem.taha2.7@gmail.com> --- bsd-user/bsd-mem.h | 18 ++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index c512a4e37569..c3e72e3b866e 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -431,4 +431,22 @@ static inline abi_long do_bsd_shmdt(abi_ulong shmaddr) return ret; } +static inline abi_long do_bsd_vadvise(void) +{ + /* See sys_ovadvise() in vm_unix.c */ + return -TARGET_EINVAL; +} + +static inline abi_long do_bsd_sbrk(void) +{ + /* see sys_sbrk() in vm_mmap.c */ + return -TARGET_EOPNOTSUPP; +} + +static inline abi_long do_bsd_sstk(void) +{ + /* see sys_sstk() in vm_mmap.c */ + return -TARGET_EOPNOTSUPP; +} + #endif /* BSD_USER_BSD_MEM_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 39e66312da1a..ca2f6fdb66e1 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -879,6 +879,18 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_shmdt(arg1); break; + case TARGET_FREEBSD_NR_freebsd11_vadvise: + ret = do_bsd_vadvise(); + break; + + case TARGET_FREEBSD_NR_sbrk: + ret = do_bsd_sbrk(); + break; + + case TARGET_FREEBSD_NR_sstk: + ret = do_bsd_sstk(); + break; + /* * Misc */ From 969298f9d7ed0ccad39203bc3656805cbf0893d4 Mon Sep 17 00:00:00 2001 From: Tejus GK Date: Tue, 3 Oct 2023 06:55:37 +0000 Subject: [PATCH 194/208] migration/vmstate: Introduce vmstate_save_state_with_err Currently, a few code paths exist in the function vmstate_save_state_v, which ultimately leads to a migration failure. However, an update in the current MigrationState for the error description is never done. vmstate.c somehow doesn't seem to allow the use of migrate_set_error due to some dependencies for unit tests. Hence, this patch introduces a new function vmstate_save_state_with_err, which will eventually propagate the error message to savevm.c where a migrate_set_error call can be eventually done. Acked-by: Peter Xu Reviewed-by: Juan Quintela Signed-off-by: Tejus GK Signed-off-by: Juan Quintela Message-ID: <20231003065538.244752-2-tejus.gk@nutanix.com> --- include/migration/vmstate.h | 4 +++- migration/savevm.c | 2 +- migration/vmstate.c | 12 +++++++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index e4db9103396f..1a31fb729395 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -1196,9 +1196,11 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, void *opaque, int version_id); int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, void *opaque, JSONWriter *vmdesc); +int vmstate_save_state_with_err(QEMUFile *f, const VMStateDescription *vmsd, + void *opaque, JSONWriter *vmdesc, Error **errp); int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd, void *opaque, JSONWriter *vmdesc, - int version_id); + int version_id, Error **errp); bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque); diff --git a/migration/savevm.c b/migration/savevm.c index bb3e99194c60..1f65294bf46c 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1000,7 +1000,7 @@ static int vmstate_save(QEMUFile *f, SaveStateEntry *se, JSONWriter *vmdesc) if (!se->vmsd) { vmstate_save_old_style(f, se, vmdesc); } else { - ret = vmstate_save_state(f, se->vmsd, se->opaque, vmdesc); + ret = vmstate_save_state_with_err(f, se->vmsd, se->opaque, vmdesc, &local_err); if (ret) { return ret; } diff --git a/migration/vmstate.c b/migration/vmstate.c index 438ea77cfa3b..dd9c76dbeb10 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -315,11 +315,17 @@ bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque) int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, void *opaque, JSONWriter *vmdesc_id) { - return vmstate_save_state_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id); + return vmstate_save_state_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id, NULL); +} + +int vmstate_save_state_with_err(QEMUFile *f, const VMStateDescription *vmsd, + void *opaque, JSONWriter *vmdesc_id, Error **errp) +{ + return vmstate_save_state_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id, errp); } int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd, - void *opaque, JSONWriter *vmdesc, int version_id) + void *opaque, JSONWriter *vmdesc, int version_id, Error **errp) { int ret = 0; const VMStateField *field = vmsd->fields; @@ -377,7 +383,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd, } else if (field->flags & VMS_VSTRUCT) { ret = vmstate_save_state_v(f, field->vmsd, curr_elem, vmdesc_loop, - field->struct_version_id); + field->struct_version_id, errp); } else { ret = field->info->put(f, curr_elem, size, field, vmdesc_loop); From 848a0503422d043d541130d5e3e2f7bc147cdef9 Mon Sep 17 00:00:00 2001 From: Tejus GK Date: Tue, 3 Oct 2023 06:55:38 +0000 Subject: [PATCH 195/208] migration: Update error description outside migration.c A few code paths exist in the source code,where a migration is marked as failed via MIGRATION_STATUS_FAILED, but the failure happens outside of migration.c In such cases, an error_report() call is made, however the current MigrationState is never updated with the error description, and hence clients like libvirt never know the actual reason for the failure. This patch covers such cases outside of migration.c and updates the error description at the appropriate places. Acked-by: Peter Xu Reviewed-by: Juan Quintela Signed-off-by: Tejus GK Signed-off-by: Juan Quintela Message-ID: <20231003065538.244752-3-tejus.gk@nutanix.com> --- migration/savevm.c | 17 ++++++++++++++--- migration/vmstate.c | 7 ++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/migration/savevm.c b/migration/savevm.c index 1f65294bf46c..60eec7c31f05 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -979,6 +979,8 @@ static void save_section_footer(QEMUFile *f, SaveStateEntry *se) static int vmstate_save(QEMUFile *f, SaveStateEntry *se, JSONWriter *vmdesc) { int ret; + Error *local_err = NULL; + MigrationState *s = migrate_get_current(); if ((!se->ops || !se->ops->save_state) && !se->vmsd) { return 0; @@ -1002,6 +1004,8 @@ static int vmstate_save(QEMUFile *f, SaveStateEntry *se, JSONWriter *vmdesc) } else { ret = vmstate_save_state_with_err(f, se->vmsd, se->opaque, vmdesc, &local_err); if (ret) { + migrate_set_error(s, local_err); + error_report_err(local_err); return ret; } } @@ -1068,10 +1072,14 @@ void qemu_savevm_send_open_return_path(QEMUFile *f) int qemu_savevm_send_packaged(QEMUFile *f, const uint8_t *buf, size_t len) { uint32_t tmp; + MigrationState *ms = migrate_get_current(); + Error *local_err = NULL; if (len > MAX_VM_CMD_PACKAGED_SIZE) { - error_report("%s: Unreasonably large packaged state: %zu", + error_setg(&local_err, "%s: Unreasonably large packaged state: %zu", __func__, len); + migrate_set_error(ms, local_err); + error_report_err(local_err); return -1; } @@ -1499,8 +1507,11 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f, * bdrv_activate_all() on the other end won't fail. */ ret = bdrv_inactivate_all(); if (ret) { - error_report("%s: bdrv_inactivate_all() failed (%d)", - __func__, ret); + Error *local_err = NULL; + error_setg(&local_err, "%s: bdrv_inactivate_all() failed (%d)", + __func__, ret); + migrate_set_error(ms, local_err); + error_report_err(local_err); qemu_file_set_error(f, ret); return ret; } diff --git a/migration/vmstate.c b/migration/vmstate.c index dd9c76dbeb10..4cde30bf2d9e 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -14,6 +14,7 @@ #include "migration.h" #include "migration/vmstate.h" #include "savevm.h" +#include "qapi/error.h" #include "qapi/qmp/json-writer.h" #include "qemu-file.h" #include "qemu/bitops.h" @@ -336,7 +337,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd, ret = vmsd->pre_save(opaque); trace_vmstate_save_state_pre_save_res(vmsd->name, ret); if (ret) { - error_report("pre-save failed: %s", vmsd->name); + error_setg(errp, "pre-save failed: %s", vmsd->name); return ret; } } @@ -389,8 +390,8 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd, vmdesc_loop); } if (ret) { - error_report("Save of field %s/%s failed", - vmsd->name, field->name); + error_setg(errp, "Save of field %s/%s failed", + vmsd->name, field->name); if (vmsd->post_save) { vmsd->post_save(opaque); } From 8ebcb4b31264a1b2e87f7c61c2d746be1974b333 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Mon, 25 Sep 2023 09:34:41 -0400 Subject: [PATCH 196/208] MAINTAINERS: Add entry for rdma migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's not obvious to many that RDMA migration is in Odd Fixes stage for a long time. Add an explicit sub entry for it (besides migration, which already covers the rdma files) to be clear on that, meanwhile add Zhijian as Reviewer, so Zhijian can see the patches and review when he still has the bandwidth. Cc: Daniel P. Berrangé Cc: Juan Quintela Cc: Markus Armbruster Cc: Zhijian Li (Fujitsu) Cc: Fabiano Rosas Acked-by: Li Zhijian Reviewed-by: Juan Quintela Signed-off-by: Peter Xu Signed-off-by: Juan Quintela Message-ID: <20230925133441.265455-1-peterx@redhat.com> --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 81625f036bdb..af730a327c7d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3222,6 +3222,15 @@ F: docs/devel/migration.rst F: qapi/migration.json F: tests/migration/ F: util/userfaultfd.c +X: migration/rdma* + +RDMA Migration +M: Juan Quintela +R: Li Zhijian +R: Peter Xu +R: Leonardo Bras +S: Odd Fixes +F: migration/rdma* Migration dirty limit and dirty page rate M: Hyman Huang From 2bace555b3bd7bb38a58b9862016c4528b331fdb Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Tue, 3 Oct 2023 10:38:47 -0400 Subject: [PATCH 197/208] migration: Add co-maintainers for migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the qemu upstream call a few hours ago, proposing Fabiano and myself as the co-maintainer for migration subsystem to help Juan. Cc: Fabiano Rosas Cc: Juan Quintela Acked-by: Fabiano Rosas Reviewed-by: Juan Quintela Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Peter Xu Signed-off-by: Juan Quintela Message-ID: <20231003143847.9245-1-peterx@redhat.com> --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index af730a327c7d..79db29878786 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3207,7 +3207,8 @@ F: scripts/checkpatch.pl Migration M: Juan Quintela -R: Peter Xu +M: Peter Xu +M: Fabiano Rosas R: Leonardo Bras S: Maintained F: hw/core/vmstate-if.c From 2ada4b63f1764d13a2b9ca9cbeb5feda46ab6851 Mon Sep 17 00:00:00 2001 From: Li Zhijian Date: Tue, 26 Sep 2023 18:01:03 +0800 Subject: [PATCH 198/208] migration/rdma: zore out head.repeat to make the error more clear Previously, we got a confusion error that complains the RDMAControlHeader.repeat: qemu-system-x86_64: rdma: Too many requests in this message (3638950032).Bailing. Actually, it's caused by an unexpected RDMAControlHeader.type. After this patch, error will become: qemu-system-x86_64: Unknown control message QEMU FILE Reviewed-by: Fabiano Rosas Reviewed-by: Peter Xu Reviewed-by: Juan Quintela Signed-off-by: Li Zhijian Signed-off-by: Juan Quintela Message-ID: <20230926100103.201564-2-lizhijian@fujitsu.com> --- migration/rdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration/rdma.c b/migration/rdma.c index 7d2726d5b699..cd5e1afe603f 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -2831,7 +2831,7 @@ static ssize_t qio_channel_rdma_writev(QIOChannel *ioc, size_t remaining = iov[i].iov_len; uint8_t * data = (void *)iov[i].iov_base; while (remaining) { - RDMAControlHeader head; + RDMAControlHeader head = {}; len = MIN(remaining, RDMA_SEND_INCREMENT); remaining -= len; From 67aeae794e51b3238ced158218edf443f8607626 Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Tue, 19 Sep 2023 13:23:44 +0300 Subject: [PATCH 199/208] i386/a-b-bootblock: factor test memory addresses out into constants So that we have less magic numbers to deal with. This also allows us to reuse these in the following commits. Reviewed-by: Peter Xu Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Juan Quintela Signed-off-by: Daniil Tatianin Signed-off-by: Juan Quintela Message-ID: <20230919102346.2117963-2-d-tatianin@yandex-team.ru> --- tests/migration/i386/a-b-bootblock.S | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/migration/i386/a-b-bootblock.S b/tests/migration/i386/a-b-bootblock.S index 3d464c7568e4..036216e4a746 100644 --- a/tests/migration/i386/a-b-bootblock.S +++ b/tests/migration/i386/a-b-bootblock.S @@ -34,6 +34,10 @@ start: # at 0x7c00 ? mov $16,%eax mov %eax,%ds +# Start from 1MB +.set TEST_MEM_START, (1024*1024) +.set TEST_MEM_END, (100*1024*1024) + mov $65,%ax mov $0x3f8,%dx outb %al,%dx @@ -41,12 +45,11 @@ start: # at 0x7c00 ? # bl keeps a counter so we limit the output speed mov $0, %bl mainloop: - # Start from 1MB - mov $(1024*1024),%eax + mov $TEST_MEM_START,%eax innerloop: incb (%eax) add $4096,%eax - cmp $(100*1024*1024),%eax + cmp $TEST_MEM_END,%eax jl innerloop inc %bl From adc1914a403e0ec89ebec4761ec8427668261c5b Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Tue, 19 Sep 2023 13:23:45 +0300 Subject: [PATCH 200/208] i386/a-b-bootblock: zero the first byte of each page on start The migration qtest all the way up to this point used to work by sheer luck relying on the contents of all pages from 1MiB to 100MiB to contain the same one value in the first byte initially. This easily breaks if we reduce the amount of RAM for the test instances from 150MiB to e.g 110MiB since that makes SeaBIOS dirty some of the pages starting at about 0x5dd2000 (~93 MiB) as it reuses those for the HighMemory allocator since commit dc88f9b72df ("malloc: use large ZoneHigh when there is enough memory"). This would result in the following errors: 12/60 qemu:qtest+qtest-x86_64 / qtest-x86_64/migration-test ERROR 2.74s killed by signal 6 SIGABRT stderr: Memory content inconsistency at 5dd2000 first_byte = cc last_byte = cb current = 9e hit_edge = 1 Memory content inconsistency at 5dd3000 first_byte = cc last_byte = cb current = 89 hit_edge = 1 Memory content inconsistency at 5dd4000 first_byte = cc last_byte = cb current = 23 hit_edge = 1 Memory content inconsistency at 5dd5000 first_byte = cc last_byte = cb current = 31 hit_edge = 1 Memory content inconsistency at 5dd6000 first_byte = cc last_byte = cb current = 70 hit_edge = 1 Memory content inconsistency at 5dd7000 first_byte = cc last_byte = cb current = ff hit_edge = 1 Memory content inconsistency at 5dd8000 first_byte = cc last_byte = cb current = 54 hit_edge = 1 Memory content inconsistency at 5dd9000 first_byte = cc last_byte = cb current = 64 hit_edge = 1 Memory content inconsistency at 5dda000 first_byte = cc last_byte = cb current = 1d hit_edge = 1 Memory content inconsistency at 5ddb000 first_byte = cc last_byte = cb current = 1a hit_edge = 1 and in another 26 pages** ERROR:../tests/qtest/migration-test.c:300:check_guests_ram: assertion failed: (bad == 0) Fix this by always zeroing the first byte of each page in the range so that we get consistent results no matter the initial contents. Fixes: ea0c6d62391 ("test: Postcopy") Signed-off-by: Daniil Tatianin Reviewed-by: Peter Xu Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Juan Quintela Signed-off-by: Juan Quintela Message-ID: <20230919102346.2117963-3-d-tatianin@yandex-team.ru> --- tests/migration/i386/a-b-bootblock.S | 9 +++++++++ tests/migration/i386/a-b-bootblock.h | 16 ++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/tests/migration/i386/a-b-bootblock.S b/tests/migration/i386/a-b-bootblock.S index 036216e4a746..6bb9999d601c 100644 --- a/tests/migration/i386/a-b-bootblock.S +++ b/tests/migration/i386/a-b-bootblock.S @@ -44,6 +44,15 @@ start: # at 0x7c00 ? # bl keeps a counter so we limit the output speed mov $0, %bl + +pre_zero: + mov $TEST_MEM_START,%eax +do_zero: + movb $0, (%eax) + add $4096,%eax + cmp $TEST_MEM_END,%eax + jl do_zero + mainloop: mov $TEST_MEM_START,%eax innerloop: diff --git a/tests/migration/i386/a-b-bootblock.h b/tests/migration/i386/a-b-bootblock.h index b7b0fce2ee1a..5b523917cef7 100644 --- a/tests/migration/i386/a-b-bootblock.h +++ b/tests/migration/i386/a-b-bootblock.h @@ -4,18 +4,18 @@ * the header and the assembler differences in your patch submission. */ unsigned char x86_bootsect[] = { - 0xfa, 0x0f, 0x01, 0x16, 0x78, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00, + 0xfa, 0x0f, 0x01, 0x16, 0x8c, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x22, 0xc0, 0x66, 0xea, 0x20, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x92, 0x0c, 0x02, 0xe6, 0x92, 0xb8, 0x10, 0x00, 0x00, 0x00, 0x8e, 0xd8, 0x66, 0xb8, 0x41, 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xb3, 0x00, 0xb8, 0x00, 0x00, 0x10, - 0x00, 0xfe, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40, - 0x06, 0x7c, 0xf2, 0xfe, 0xc3, 0x80, 0xe3, 0x3f, 0x75, 0xe6, 0x66, 0xb8, - 0x42, 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xeb, 0xdb, 0x8d, 0x76, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x9a, 0xcf, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, - 0x27, 0x00, 0x60, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00, + 0x40, 0x06, 0x7c, 0xf1, 0xb8, 0x00, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x05, + 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40, 0x06, 0x7c, 0xf2, 0xfe, + 0xc3, 0x80, 0xe3, 0x3f, 0x75, 0xe6, 0x66, 0xb8, 0x42, 0x00, 0x66, 0xba, + 0xf8, 0x03, 0xee, 0xeb, 0xdb, 0x8d, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, 0x27, 0x00, 0x74, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, From b28e3ecf0de1bc77b6a1a520e3c223f37b5afce2 Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Tue, 19 Sep 2023 13:23:46 +0300 Subject: [PATCH 201/208] s390x/a-b-bios: zero the first byte of each page on start Same as with the x86 verison of this test, we relied on the contents of all pages in RAM to be the same across the entire test range, which is very fragile. Zero the first byte of each page before running the increment loop to fix this. Fixes: 5571dc824b ("tests/migration: Enable the migration test on s390x, too") Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Peter Xu Reviewed-by: Juan Quintela Signed-off-by: Daniil Tatianin Signed-off-by: Juan Quintela Message-ID: <20230919102346.2117963-4-d-tatianin@yandex-team.ru> --- tests/migration/s390x/a-b-bios.c | 8 + tests/migration/s390x/a-b-bios.h | 380 +++++++++++++++++-------------- 2 files changed, 211 insertions(+), 177 deletions(-) diff --git a/tests/migration/s390x/a-b-bios.c b/tests/migration/s390x/a-b-bios.c index a0327cd153b6..ff99a3ef57d7 100644 --- a/tests/migration/s390x/a-b-bios.c +++ b/tests/migration/s390x/a-b-bios.c @@ -27,6 +27,14 @@ void main(void) sclp_setup(); sclp_print("A"); + /* + * Make sure all of the pages have consistent contents before incrementing + * the first byte below. + */ + for (addr = START_ADDRESS; addr < END_ADDRESS; addr += 4096) { + *(volatile char *)addr = 0; + } + while (1) { for (addr = START_ADDRESS; addr < END_ADDRESS; addr += 4096) { *(volatile char *)addr += 1; /* Change pages */ diff --git a/tests/migration/s390x/a-b-bios.h b/tests/migration/s390x/a-b-bios.h index e722dc7c40f0..96103dadbbf3 100644 --- a/tests/migration/s390x/a-b-bios.h +++ b/tests/migration/s390x/a-b-bios.h @@ -6,10 +6,10 @@ unsigned char s390x_elf[] = { 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xa8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x07, 0x00, 0x40, - 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x00, 0x00, @@ -21,140 +21,154 @@ unsigned char s390x_elf[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xac, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x98, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xb8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x17, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xb8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x18, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, + 0x00, 0x00, 0x07, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xb8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xb8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x64, 0x74, 0xe5, 0x51, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x64, 0x74, 0xe5, 0x52, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xb8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x17, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xb8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x6c, 0x64, 0x36, 0x34, 0x2e, 0x73, 0x6f, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0xef, 0xf0, 0x70, - 0x00, 0x24, 0xa7, 0xfb, 0xff, 0x60, 0xc0, 0xe5, 0x00, 0x00, 0x01, 0x1f, - 0xc0, 0x20, 0x00, 0x00, 0x02, 0x64, 0xc0, 0xe5, 0x00, 0x00, 0x01, 0x35, - 0xa5, 0x1e, 0x00, 0x10, 0xa7, 0x29, 0x63, 0x00, 0xe3, 0x30, 0x10, 0x00, - 0x00, 0x90, 0xa7, 0x3a, 0x00, 0x01, 0x42, 0x30, 0x10, 0x00, 0xa7, 0x1b, - 0x10, 0x00, 0xa7, 0x27, 0xff, 0xf7, 0xc0, 0x20, 0x00, 0x00, 0x02, 0x50, - 0xa7, 0xf4, 0xff, 0xeb, 0x07, 0x07, 0x07, 0x07, 0xc0, 0xf0, 0x00, 0x00, - 0x56, 0xc4, 0xc0, 0x20, 0x00, 0x00, 0x0a, 0xbd, 0xc0, 0x30, 0x00, 0x00, - 0x56, 0xbe, 0xb9, 0x0b, 0x00, 0x32, 0xb9, 0x02, 0x00, 0x33, 0xa7, 0x84, - 0x00, 0x19, 0xa7, 0x3b, 0xff, 0xff, 0xeb, 0x43, 0x00, 0x08, 0x00, 0x0c, - 0xb9, 0x02, 0x00, 0x44, 0xb9, 0x04, 0x00, 0x12, 0xa7, 0x84, 0x00, 0x09, - 0xd7, 0xff, 0x10, 0x00, 0x10, 0x00, 0x41, 0x10, 0x11, 0x00, 0xa7, 0x47, - 0xff, 0xfb, 0xc0, 0x20, 0x00, 0x00, 0x00, 0x07, 0x44, 0x30, 0x20, 0x00, - 0xa7, 0xf4, 0xff, 0xb6, 0xd7, 0x00, 0x10, 0x00, 0x10, 0x00, 0xc0, 0x10, - 0x00, 0x00, 0x00, 0x29, 0xb2, 0xb2, 0x10, 0x00, 0xeb, 0x00, 0xf0, 0x00, - 0x00, 0x25, 0x96, 0x02, 0xf0, 0x06, 0xeb, 0x00, 0xf0, 0x00, 0x00, 0x2f, - 0xc0, 0x10, 0x00, 0x00, 0x00, 0x11, 0xe3, 0x10, 0x01, 0xb8, 0x00, 0x24, - 0xc0, 0x10, 0x00, 0x00, 0x00, 0x26, 0xd2, 0x07, 0x01, 0xb0, 0x10, 0x00, - 0xc0, 0x10, 0x00, 0x00, 0x00, 0x18, 0xb2, 0xb2, 0x10, 0x00, 0xeb, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf0, 0xeb, 0xef, 0xf0, 0x70, + 0x00, 0x24, 0xa7, 0xfb, 0xff, 0x60, 0xc0, 0xe5, 0x00, 0x00, 0x01, 0x5f, + 0xc0, 0x20, 0x00, 0x00, 0x02, 0xa8, 0xc0, 0xe5, 0x00, 0x00, 0x01, 0x75, + 0xa5, 0x2e, 0x00, 0x10, 0xa7, 0x19, 0x63, 0x00, 0x92, 0x00, 0x20, 0x00, + 0xa7, 0x2b, 0x10, 0x00, 0xa7, 0x17, 0xff, 0xfc, 0xa5, 0x1e, 0x00, 0x10, + 0xa7, 0x29, 0x63, 0x00, 0xe3, 0x30, 0x10, 0x00, 0x00, 0x90, 0xa7, 0x3a, + 0x00, 0x01, 0x42, 0x30, 0x10, 0x00, 0xa7, 0x1b, 0x10, 0x00, 0xa7, 0x27, + 0xff, 0xf7, 0xc0, 0x20, 0x00, 0x00, 0x02, 0x8a, 0xc0, 0xe5, 0x00, 0x00, + 0x01, 0x56, 0xa7, 0xf4, 0xff, 0xeb, 0x07, 0x07, 0xc0, 0xf0, 0x00, 0x00, + 0x4e, 0x5c, 0xc0, 0x20, 0x00, 0x00, 0x00, 0x7d, 0xe3, 0x20, 0x20, 0x00, + 0x00, 0x04, 0xc0, 0x30, 0x00, 0x00, 0x96, 0xa3, 0xb9, 0x0b, 0x00, 0x32, + 0xb9, 0x02, 0x00, 0x33, 0xa7, 0x84, 0x00, 0x19, 0xa7, 0x3b, 0xff, 0xff, + 0xeb, 0x43, 0x00, 0x08, 0x00, 0x0c, 0xb9, 0x02, 0x00, 0x44, 0xb9, 0x04, + 0x00, 0x12, 0xa7, 0x84, 0x00, 0x09, 0xd7, 0xff, 0x10, 0x00, 0x10, 0x00, + 0x41, 0x10, 0x11, 0x00, 0xa7, 0x47, 0xff, 0xfb, 0xc0, 0x20, 0x00, 0x00, + 0x00, 0x0d, 0x44, 0x30, 0x20, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x00, 0x5b, + 0xd2, 0x0f, 0x01, 0xd0, 0x20, 0x00, 0xa7, 0xf4, 0xff, 0xa1, 0xd7, 0x00, + 0x10, 0x00, 0x10, 0x00, 0xc0, 0x10, 0x00, 0x00, 0x00, 0x50, 0xb2, 0xb2, + 0x10, 0x00, 0xa7, 0xf4, 0x00, 0x00, 0xeb, 0x00, 0xf0, 0x00, 0x00, 0x25, + 0x96, 0x02, 0xf0, 0x06, 0xeb, 0x00, 0xf0, 0x00, 0x00, 0x2f, 0xc0, 0x10, + 0x00, 0x00, 0x00, 0x2a, 0xe3, 0x10, 0x01, 0xb8, 0x00, 0x24, 0xc0, 0x10, + 0x00, 0x00, 0x00, 0x4b, 0xd2, 0x07, 0x01, 0xb0, 0x10, 0x00, 0xc0, 0x10, + 0x00, 0x00, 0x00, 0x3d, 0xb2, 0xb2, 0x10, 0x00, 0xeb, 0x66, 0xf0, 0x00, + 0x00, 0x25, 0x96, 0xff, 0xf0, 0x04, 0xeb, 0x66, 0xf0, 0x00, 0x00, 0x2f, + 0xc0, 0x10, 0x00, 0x00, 0x00, 0x1a, 0xe3, 0x10, 0x01, 0xf8, 0x00, 0x24, + 0xc0, 0x10, 0x00, 0x00, 0x00, 0x36, 0xd2, 0x07, 0x01, 0xf0, 0x10, 0x00, + 0xc0, 0x10, 0x00, 0x00, 0x00, 0x24, 0xb2, 0xb2, 0x10, 0x00, 0xeb, 0x00, 0xf0, 0x00, 0x00, 0x25, 0x94, 0xfd, 0xf0, 0x06, 0xeb, 0x00, 0xf0, 0x00, - 0x00, 0x2f, 0x07, 0xfe, 0x07, 0x07, 0x07, 0x07, 0x00, 0x02, 0x00, 0x01, + 0x00, 0x2f, 0x07, 0xfe, 0xeb, 0x66, 0xf0, 0x00, 0x00, 0x25, 0x94, 0x00, + 0xf0, 0x04, 0xeb, 0x66, 0xf0, 0x00, 0x00, 0x2f, 0x07, 0xfe, 0x07, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf0, 0x00, 0x02, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, - 0xeb, 0xbf, 0xf0, 0x58, 0x00, 0x24, 0xc0, 0x10, 0x00, 0x00, 0x0e, 0x59, - 0xa7, 0xfb, 0xff, 0x60, 0xb2, 0x20, 0x00, 0x21, 0xb2, 0x22, 0x00, 0xb0, - 0x88, 0xb0, 0x00, 0x1c, 0xc0, 0xe5, 0xff, 0xff, 0xff, 0xba, 0xa7, 0xbe, - 0x00, 0x03, 0xa7, 0x84, 0x00, 0x13, 0xa7, 0xbe, 0x00, 0x02, 0xa7, 0x28, - 0x00, 0x00, 0xa7, 0x74, 0x00, 0x04, 0xa7, 0x28, 0xff, 0xfe, 0xe3, 0x40, - 0xf1, 0x10, 0x00, 0x04, 0xb9, 0x14, 0x00, 0x22, 0xeb, 0xbf, 0xf0, 0xf8, - 0x00, 0x04, 0x07, 0xf4, 0xa7, 0x28, 0xff, 0xff, 0xa7, 0xf4, 0xff, 0xf5, - 0x07, 0x07, 0x07, 0x07, 0xeb, 0xbf, 0xf0, 0x58, 0x00, 0x24, 0xc0, 0xd0, - 0x00, 0x00, 0x01, 0x21, 0xa7, 0xfb, 0xff, 0x60, 0xa7, 0xb9, 0x00, 0x00, - 0xa7, 0x19, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0x0e, 0x24, 0xa7, 0x3b, - 0x00, 0x01, 0xa7, 0x37, 0x00, 0x23, 0xc0, 0x20, 0x00, 0x00, 0x0e, 0x1d, - 0x18, 0x31, 0xa7, 0x1a, 0x00, 0x06, 0x40, 0x10, 0x20, 0x08, 0xa7, 0x3a, - 0x00, 0x0e, 0xa7, 0x18, 0x1a, 0x00, 0x40, 0x30, 0x20, 0x00, 0x92, 0x00, - 0x20, 0x02, 0x40, 0x10, 0x20, 0x0a, 0xe3, 0x20, 0xd0, 0x00, 0x00, 0x04, - 0xc0, 0xe5, 0xff, 0xff, 0xff, 0xac, 0xe3, 0x40, 0xf1, 0x10, 0x00, 0x04, - 0xb9, 0x04, 0x00, 0x2b, 0xeb, 0xbf, 0xf0, 0xf8, 0x00, 0x04, 0x07, 0xf4, - 0xb9, 0x04, 0x00, 0x51, 0xa7, 0x5b, 0x00, 0x01, 0xa7, 0x09, 0x0f, 0xf7, - 0xb9, 0x21, 0x00, 0x50, 0xa7, 0x24, 0xff, 0xd7, 0x41, 0xeb, 0x20, 0x00, - 0x95, 0x0a, 0xe0, 0x00, 0xa7, 0x74, 0x00, 0x08, 0x41, 0x11, 0x40, 0x0e, - 0x92, 0x0d, 0x10, 0x00, 0xb9, 0x04, 0x00, 0x15, 0x43, 0x5b, 0x20, 0x00, - 0x42, 0x51, 0x40, 0x0e, 0xa7, 0xbb, 0x00, 0x01, 0x41, 0x10, 0x10, 0x01, - 0xa7, 0xf4, 0xff, 0xbf, 0xc0, 0x50, 0x00, 0x00, 0x00, 0xd4, 0xc0, 0x10, - 0x00, 0x00, 0x0d, 0xd9, 0xa7, 0x48, 0x00, 0x1c, 0x40, 0x40, 0x10, 0x00, - 0x50, 0x20, 0x10, 0x0c, 0xa7, 0x48, 0x00, 0x04, 0xe3, 0x20, 0x50, 0x00, - 0x00, 0x04, 0x40, 0x40, 0x10, 0x0a, 0x50, 0x30, 0x10, 0x10, 0xc0, 0xf4, - 0xff, 0xff, 0xff, 0x6b, 0xa7, 0x39, 0x00, 0x40, 0xa7, 0x29, 0x00, 0x00, - 0xc0, 0xf4, 0xff, 0xff, 0xff, 0xe4, 0x07, 0x07, 0xb9, 0x04, 0x00, 0x13, - 0xa7, 0x2a, 0xff, 0xff, 0xb9, 0x04, 0x00, 0x34, 0xa7, 0x48, 0x00, 0x01, - 0x15, 0x24, 0xa7, 0x24, 0x00, 0x07, 0xb9, 0x04, 0x00, 0x21, 0xc0, 0xf4, - 0xff, 0xff, 0xff, 0x7f, 0xa7, 0x29, 0xff, 0xff, 0x07, 0xfe, 0x07, 0x07, - 0xa7, 0x39, 0x00, 0x00, 0x41, 0x13, 0x20, 0x00, 0x95, 0x00, 0x10, 0x00, - 0xa7, 0x74, 0x00, 0x05, 0xc0, 0xf4, 0xff, 0xff, 0xff, 0x70, 0xa7, 0x3b, - 0x00, 0x01, 0xa7, 0xf4, 0xff, 0xf5, 0x07, 0x07, 0xeb, 0xbf, 0xf0, 0x58, - 0x00, 0x24, 0xc0, 0xd0, 0x00, 0x00, 0x00, 0x91, 0xa7, 0xfb, 0xff, 0x60, - 0xb9, 0x04, 0x00, 0xb2, 0xa7, 0x19, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x00, - 0x0d, 0x8c, 0x92, 0x00, 0x20, 0x00, 0xa7, 0x2b, 0x00, 0x01, 0xa7, 0x17, - 0xff, 0xfc, 0xc0, 0x10, 0x00, 0x00, 0x0d, 0x83, 0xa7, 0x28, 0x00, 0x20, - 0x40, 0x20, 0x10, 0x00, 0xe3, 0x20, 0xd0, 0x00, 0x00, 0x04, 0xc0, 0xe5, - 0xff, 0xff, 0xff, 0x1d, 0x12, 0x22, 0xa7, 0x74, 0x00, 0x17, 0xa7, 0x19, - 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x75, 0xc0, 0x50, 0x00, 0x00, - 0x0d, 0x7a, 0xa7, 0x29, 0x00, 0x08, 0xe3, 0x31, 0x50, 0x00, 0x00, 0x90, - 0x43, 0x33, 0x40, 0x00, 0x42, 0x31, 0xb0, 0x00, 0xa7, 0x1b, 0x00, 0x01, - 0xa7, 0x27, 0xff, 0xf7, 0xe3, 0x40, 0xf1, 0x10, 0x00, 0x04, 0xeb, 0xbf, - 0xf0, 0xf8, 0x00, 0x04, 0x07, 0xf4, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0xeb, 0xaf, 0xf0, 0x50, 0x00, 0x24, 0xc0, 0xd0, 0x00, 0x00, 0x00, 0x51, - 0xa7, 0xfb, 0xff, 0x60, 0xa7, 0x19, 0x0f, 0xf8, 0xb9, 0x21, 0x00, 0x31, - 0xb9, 0x04, 0x00, 0xa2, 0xa7, 0xc4, 0x00, 0x2d, 0xa7, 0xb9, 0x0f, 0xf8, - 0xc0, 0x10, 0x00, 0x00, 0x0d, 0x42, 0xa7, 0x28, 0x10, 0x00, 0x40, 0x20, - 0x10, 0x00, 0x92, 0x00, 0x10, 0x02, 0xe3, 0x20, 0xd0, 0x00, 0x00, 0x04, - 0xc0, 0xe5, 0xff, 0xff, 0xfe, 0xda, 0xa7, 0xbb, 0x00, 0x01, 0xa7, 0x19, - 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x0d, 0x2f, 0xa7, 0xb7, 0x00, 0x17, - 0xc0, 0x10, 0x00, 0x00, 0x0d, 0x2a, 0xe3, 0x40, 0xf1, 0x10, 0x00, 0x04, - 0xe3, 0x20, 0x10, 0x08, 0x00, 0x91, 0xa7, 0x2a, 0xff, 0xf9, 0xb9, 0x14, - 0x00, 0x22, 0xeb, 0xaf, 0xf0, 0xf0, 0x00, 0x04, 0x07, 0xf4, 0xb9, 0x04, - 0x00, 0xb3, 0xa7, 0xf4, 0xff, 0xd5, 0x43, 0x31, 0x20, 0x0f, 0x42, 0x31, - 0xa0, 0x00, 0xa7, 0x1b, 0x00, 0x01, 0xa7, 0xf4, 0xff, 0xe3, 0x07, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, 0x2e, 0x2e, 0x2e, 0x2e, + 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0xeb, 0xbf, 0xf0, 0x58, + 0x00, 0x24, 0xc0, 0x10, 0x00, 0x00, 0x4e, 0x0d, 0xa7, 0xfb, 0xff, 0x60, + 0xb2, 0x20, 0x00, 0x21, 0xb2, 0x22, 0x00, 0xb0, 0x88, 0xb0, 0x00, 0x1c, + 0xc0, 0xe5, 0xff, 0xff, 0xff, 0x91, 0xa7, 0xbe, 0x00, 0x03, 0xa7, 0x84, + 0x00, 0x13, 0xa7, 0xbe, 0x00, 0x02, 0xa7, 0x28, 0x00, 0x00, 0xa7, 0x74, + 0x00, 0x04, 0xa7, 0x28, 0xff, 0xfe, 0xe3, 0x40, 0xf1, 0x10, 0x00, 0x04, + 0xb9, 0x14, 0x00, 0x22, 0xeb, 0xbf, 0xf0, 0xf8, 0x00, 0x04, 0x07, 0xf4, + 0xa7, 0x28, 0xff, 0xff, 0xa7, 0xf4, 0xff, 0xf5, 0x07, 0x07, 0x07, 0x07, + 0xeb, 0xbf, 0xf0, 0x58, 0x00, 0x24, 0xc0, 0xd0, 0x00, 0x00, 0x01, 0x25, + 0xa7, 0xfb, 0xff, 0x60, 0xa7, 0xb9, 0x00, 0x00, 0xa7, 0x19, 0x00, 0x00, + 0xc0, 0x40, 0x00, 0x00, 0x4d, 0xd8, 0xa7, 0x3b, 0x00, 0x01, 0xa7, 0x37, + 0x00, 0x23, 0xc0, 0x20, 0x00, 0x00, 0x4d, 0xd1, 0x18, 0x31, 0xa7, 0x1a, + 0x00, 0x06, 0x40, 0x10, 0x20, 0x08, 0xa7, 0x3a, 0x00, 0x0e, 0xa7, 0x18, + 0x1a, 0x00, 0x40, 0x30, 0x20, 0x00, 0x92, 0x00, 0x20, 0x02, 0x40, 0x10, + 0x20, 0x0a, 0xe3, 0x20, 0xd0, 0x00, 0x00, 0x04, 0xc0, 0xe5, 0xff, 0xff, + 0xff, 0xac, 0xe3, 0x40, 0xf1, 0x10, 0x00, 0x04, 0xb9, 0x04, 0x00, 0x2b, + 0xeb, 0xbf, 0xf0, 0xf8, 0x00, 0x04, 0x07, 0xf4, 0xb9, 0x04, 0x00, 0x51, + 0xa7, 0x5b, 0x00, 0x01, 0xa7, 0x09, 0x0f, 0xf7, 0xb9, 0x21, 0x00, 0x50, + 0xa7, 0x24, 0xff, 0xd7, 0x41, 0xeb, 0x20, 0x00, 0x95, 0x0a, 0xe0, 0x00, + 0xa7, 0x74, 0x00, 0x08, 0x41, 0x11, 0x40, 0x0e, 0x92, 0x0d, 0x10, 0x00, + 0xb9, 0x04, 0x00, 0x15, 0x43, 0x5b, 0x20, 0x00, 0x42, 0x51, 0x40, 0x0e, + 0xa7, 0xbb, 0x00, 0x01, 0x41, 0x10, 0x10, 0x01, 0xa7, 0xf4, 0xff, 0xbf, + 0xc0, 0x50, 0x00, 0x00, 0x00, 0xd8, 0xc0, 0x10, 0x00, 0x00, 0x4d, 0x8d, + 0xa7, 0x48, 0x00, 0x1c, 0x40, 0x40, 0x10, 0x00, 0x50, 0x20, 0x10, 0x0c, + 0xa7, 0x48, 0x00, 0x04, 0xe3, 0x20, 0x50, 0x00, 0x00, 0x04, 0x40, 0x40, + 0x10, 0x0a, 0x50, 0x30, 0x10, 0x10, 0xc0, 0xf4, 0xff, 0xff, 0xff, 0x6b, + 0xa7, 0x39, 0x00, 0x40, 0xa7, 0x29, 0x00, 0x00, 0xc0, 0xf4, 0xff, 0xff, + 0xff, 0xe4, 0x07, 0x07, 0xb9, 0x04, 0x00, 0x13, 0xa7, 0x2a, 0xff, 0xff, + 0xb9, 0x04, 0x00, 0x34, 0xa7, 0x48, 0x00, 0x01, 0x15, 0x24, 0xa7, 0x24, + 0x00, 0x07, 0xb9, 0x04, 0x00, 0x21, 0xc0, 0xf4, 0xff, 0xff, 0xff, 0x7f, + 0xa7, 0x29, 0xff, 0xff, 0x07, 0xfe, 0x07, 0x07, 0xa7, 0x39, 0x00, 0x00, + 0x41, 0x13, 0x20, 0x00, 0x95, 0x00, 0x10, 0x00, 0xa7, 0x74, 0x00, 0x05, + 0xc0, 0xf4, 0xff, 0xff, 0xff, 0x70, 0xa7, 0x3b, 0x00, 0x01, 0xa7, 0xf4, + 0xff, 0xf5, 0x07, 0x07, 0xeb, 0xbf, 0xf0, 0x58, 0x00, 0x24, 0xc0, 0xd0, + 0x00, 0x00, 0x00, 0x95, 0xa7, 0xfb, 0xff, 0x60, 0xb9, 0x04, 0x00, 0xb2, + 0xa7, 0x19, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x00, 0x4d, 0x40, 0x92, 0x00, + 0x20, 0x00, 0xa7, 0x2b, 0x00, 0x01, 0xa7, 0x17, 0xff, 0xfc, 0xc0, 0x10, + 0x00, 0x00, 0x4d, 0x37, 0xa7, 0x28, 0x10, 0x00, 0x40, 0x20, 0x10, 0x00, + 0xe3, 0x20, 0xd0, 0x00, 0x00, 0x04, 0xc0, 0xe5, 0xff, 0xff, 0xff, 0x1d, + 0x12, 0x22, 0xa7, 0x74, 0x00, 0x19, 0xa7, 0x19, 0x00, 0x00, 0xc0, 0x40, + 0x00, 0x00, 0x00, 0x79, 0xa7, 0x39, 0x00, 0x08, 0xc0, 0x20, 0x00, 0x00, + 0x4d, 0x2c, 0x41, 0x21, 0x20, 0x00, 0xe3, 0x20, 0x20, 0x00, 0x00, 0x90, + 0x43, 0x22, 0x40, 0x00, 0x42, 0x21, 0xb0, 0x00, 0xa7, 0x1b, 0x00, 0x01, + 0xa7, 0x37, 0xff, 0xf2, 0xe3, 0x40, 0xf1, 0x10, 0x00, 0x04, 0xeb, 0xbf, + 0xf0, 0xf8, 0x00, 0x04, 0x07, 0xf4, 0x07, 0x07, 0xeb, 0xaf, 0xf0, 0x50, + 0x00, 0x24, 0xc0, 0xd0, 0x00, 0x00, 0x00, 0x55, 0xa7, 0xfb, 0xff, 0x60, + 0xa7, 0x19, 0x0f, 0xf8, 0xb9, 0x21, 0x00, 0x31, 0xb9, 0x04, 0x00, 0xa2, + 0xa7, 0xc4, 0x00, 0x2a, 0xa7, 0xb9, 0x0f, 0xf8, 0xc0, 0x10, 0x00, 0x00, + 0x4c, 0xf6, 0xa7, 0x28, 0x10, 0x00, 0x40, 0x20, 0x10, 0x00, 0x92, 0x00, + 0x10, 0x02, 0xe3, 0x20, 0xd0, 0x00, 0x00, 0x04, 0xc0, 0xe5, 0xff, 0xff, + 0xfe, 0xda, 0xa7, 0xbb, 0x00, 0x01, 0xa7, 0x19, 0x00, 0x00, 0xa7, 0xb7, + 0x00, 0x17, 0xc0, 0x10, 0x00, 0x00, 0x4c, 0xe1, 0xe3, 0x40, 0xf1, 0x10, + 0x00, 0x04, 0xe3, 0x20, 0x10, 0x08, 0x00, 0x91, 0xa7, 0x2a, 0xff, 0xf9, + 0xb9, 0x14, 0x00, 0x22, 0xeb, 0xaf, 0xf0, 0xf0, 0x00, 0x04, 0x07, 0xf4, + 0xb9, 0x04, 0x00, 0xb3, 0xa7, 0xf4, 0xff, 0xd8, 0xc0, 0x20, 0x00, 0x00, + 0x4c, 0xcc, 0x41, 0x31, 0xa0, 0x00, 0x41, 0x21, 0x20, 0x00, 0xa7, 0x1b, + 0x00, 0x01, 0xd2, 0x00, 0x30, 0x00, 0x20, 0x0f, 0xa7, 0xf4, 0xff, 0xdd, + 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x3c, 0x28, 0x2b, 0x7c, 0x26, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x2e, 0x2d, 0x2f, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2c, 0x25, 0x5f, 0x3e, 0x3f, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x60, 0x3a, 0x23, - 0x40, 0x27, 0x3d, 0x22, 0x2e, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x6a, 0x6b, 0x6c, - 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, 0x26, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x2e, + 0x2d, 0x2f, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2c, + 0x25, 0x5f, 0x3e, 0x3f, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, 0x2e, 0x61, 0x62, 0x63, + 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x41, 0x42, 0x43, - 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x30, 0x31, 0x32, 0x33, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x41, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2e, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x41, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xff, 0xfe, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, @@ -163,91 +177,103 @@ unsigned char s390x_elf[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6f, 0xff, 0xff, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xff, 0xff, 0xfb, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x6f, 0xff, 0xff, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x43, 0x43, 0x3a, 0x20, 0x28, 0x47, 0x4e, 0x55, 0x29, 0x20, 0x38, - 0x2e, 0x32, 0x2e, 0x31, 0x20, 0x32, 0x30, 0x31, 0x38, 0x30, 0x39, 0x30, - 0x35, 0x20, 0x28, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, 0x38, - 0x2e, 0x32, 0x2e, 0x31, 0x2d, 0x33, 0x29, 0x00, 0x00, 0x2e, 0x73, 0x68, - 0x73, 0x74, 0x72, 0x74, 0x61, 0x62, 0x00, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x00, 0x2e, 0x67, 0x6e, 0x75, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x00, 0x2e, 0x64, 0x79, 0x6e, 0x73, 0x79, 0x6d, 0x00, 0x2e, 0x64, 0x79, - 0x6e, 0x73, 0x74, 0x72, 0x00, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x00, 0x2e, - 0x72, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x00, 0x2e, 0x64, 0x79, 0x6e, 0x61, - 0x6d, 0x69, 0x63, 0x00, 0x2e, 0x67, 0x6f, 0x74, 0x00, 0x2e, 0x62, 0x73, - 0x73, 0x00, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, + 0x00, 0x00, 0x17, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x43, 0x43, 0x3a, + 0x20, 0x28, 0x55, 0x62, 0x75, 0x6e, 0x74, 0x75, 0x20, 0x31, 0x31, 0x2e, + 0x34, 0x2e, 0x30, 0x2d, 0x31, 0x75, 0x62, 0x75, 0x6e, 0x74, 0x75, 0x31, + 0x7e, 0x32, 0x32, 0x2e, 0x30, 0x34, 0x29, 0x20, 0x31, 0x31, 0x2e, 0x34, + 0x2e, 0x30, 0x00, 0x00, 0x2e, 0x73, 0x68, 0x73, 0x74, 0x72, 0x74, 0x61, + 0x62, 0x00, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x00, 0x2e, 0x67, + 0x6e, 0x75, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x00, 0x2e, 0x64, 0x79, 0x6e, + 0x73, 0x79, 0x6d, 0x00, 0x2e, 0x64, 0x79, 0x6e, 0x73, 0x74, 0x72, 0x00, + 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x2e, 0x64, 0x79, 0x6e, 0x00, 0x2e, 0x74, + 0x65, 0x78, 0x74, 0x00, 0x2e, 0x72, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x00, + 0x2e, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x00, 0x2e, 0x67, 0x6f, + 0x74, 0x00, 0x2e, 0x62, 0x73, 0x73, 0x00, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, + 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x13, 0x6f, 0xff, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x6f, 0xff, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x25, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x01, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x05, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xe8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, - 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, - 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x37, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x88, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x88, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x17, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xb8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x4e, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xd8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x09, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x24, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; From 2a9e2e595f2bc81c07e2f06ef9ba7d4c68897f1c Mon Sep 17 00:00:00 2001 From: Steve Sistare Date: Fri, 8 Sep 2023 07:22:10 -0700 Subject: [PATCH 202/208] migration: file URI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend the migration URI to support file:. This can be used for any migration scenario that does not require a reverse path. It can be used as an alternative to 'exec:cat > file' in minimized containers that do not contain /bin/sh, and it is easier to use than the fd: URI. It can be used in HMP commands, and as a qemu command-line parameter. For best performance, guest ram should be shared and x-ignore-shared should be true, so guest pages are not written to the file, in which case the guest may remain running. If ram is not so configured, then the user is advised to stop the guest first. Otherwise, a busy guest may re-dirty the same page, causing it to be appended to the file multiple times, and the file may grow unboundedly. That issue is being addressed in the "fixed-ram" patch series. Signed-off-by: Steve Sistare Tested-by: Michael Galaxy Reviewed-by: Michael Galaxy Reviewed-by: Fabiano Rosas Reviewed-by: Peter Xu Reviewed-by: Daniel P. Berrangé Reviewed-by: Juan Quintela Signed-off-by: Juan Quintela Message-ID: <1694182931-61390-2-git-send-email-steven.sistare@oracle.com> --- migration/file.c | 62 ++++++++++++++++++++++++++++++++++++++++++ migration/file.h | 14 ++++++++++ migration/meson.build | 1 + migration/migration.c | 5 ++++ migration/trace-events | 4 +++ qemu-options.hx | 6 +++- 6 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 migration/file.c create mode 100644 migration/file.h diff --git a/migration/file.c b/migration/file.c new file mode 100644 index 000000000000..0a65c43fdd7c --- /dev/null +++ b/migration/file.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021-2023 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "channel.h" +#include "file.h" +#include "migration.h" +#include "io/channel-file.h" +#include "io/channel-util.h" +#include "trace.h" + +void file_start_outgoing_migration(MigrationState *s, const char *filename, + Error **errp) +{ + g_autoptr(QIOChannelFile) fioc = NULL; + QIOChannel *ioc; + + trace_migration_file_outgoing(filename); + + fioc = qio_channel_file_new_path(filename, O_CREAT | O_WRONLY | O_TRUNC, + 0600, errp); + if (!fioc) { + return; + } + + ioc = QIO_CHANNEL(fioc); + qio_channel_set_name(ioc, "migration-file-outgoing"); + migration_channel_connect(s, ioc, NULL, NULL); +} + +static gboolean file_accept_incoming_migration(QIOChannel *ioc, + GIOCondition condition, + gpointer opaque) +{ + migration_channel_process_incoming(ioc); + object_unref(OBJECT(ioc)); + return G_SOURCE_REMOVE; +} + +void file_start_incoming_migration(const char *filename, Error **errp) +{ + QIOChannelFile *fioc = NULL; + QIOChannel *ioc; + + trace_migration_file_incoming(filename); + + fioc = qio_channel_file_new_path(filename, O_RDONLY, 0, errp); + if (!fioc) { + return; + } + + ioc = QIO_CHANNEL(fioc); + qio_channel_set_name(QIO_CHANNEL(ioc), "migration-file-incoming"); + qio_channel_add_watch_full(ioc, G_IO_IN, + file_accept_incoming_migration, + NULL, NULL, + g_main_context_get_thread_default()); +} diff --git a/migration/file.h b/migration/file.h new file mode 100644 index 000000000000..90fa4849e090 --- /dev/null +++ b/migration/file.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021-2023 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef QEMU_MIGRATION_FILE_H +#define QEMU_MIGRATION_FILE_H +void file_start_incoming_migration(const char *filename, Error **errp); + +void file_start_outgoing_migration(MigrationState *s, const char *filename, + Error **errp); +#endif diff --git a/migration/meson.build b/migration/meson.build index 1ae28523a109..92b1cc429783 100644 --- a/migration/meson.build +++ b/migration/meson.build @@ -16,6 +16,7 @@ system_ss.add(files( 'dirtyrate.c', 'exec.c', 'fd.c', + 'file.c', 'global_state.c', 'migration-hmp-cmds.c', 'migration.c', diff --git a/migration/migration.c b/migration/migration.c index 6d3cf5d5cd89..585d3c8f55a6 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -20,6 +20,7 @@ #include "migration/blocker.h" #include "exec.h" #include "fd.h" +#include "file.h" #include "socket.h" #include "sysemu/runstate.h" #include "sysemu/sysemu.h" @@ -449,6 +450,8 @@ static void qemu_start_incoming_migration(const char *uri, Error **errp) exec_start_incoming_migration(p, errp); } else if (strstart(uri, "fd:", &p)) { fd_start_incoming_migration(p, errp); + } else if (strstart(uri, "file:", &p)) { + file_start_incoming_migration(p, errp); } else { error_setg(errp, "unknown migration protocol: %s", uri); } @@ -1702,6 +1705,8 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, exec_start_outgoing_migration(s, p, &local_err); } else if (strstart(uri, "fd:", &p)) { fd_start_outgoing_migration(s, p, &local_err); + } else if (strstart(uri, "file:", &p)) { + file_start_outgoing_migration(s, p, &local_err); } else { error_setg(&local_err, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol"); diff --git a/migration/trace-events b/migration/trace-events index 63483732ce81..3e9649ab2a71 100644 --- a/migration/trace-events +++ b/migration/trace-events @@ -311,6 +311,10 @@ migration_exec_incoming(const char *cmd) "cmd=%s" migration_fd_outgoing(int fd) "fd=%d" migration_fd_incoming(int fd) "fd=%d" +# file.c +migration_file_outgoing(const char *filename) "filename=%s" +migration_file_incoming(const char *filename) "filename=%s" + # socket.c migration_socket_incoming_accepted(void) "" migration_socket_outgoing_connected(const char *hostname) "hostname=%s" diff --git a/qemu-options.hx b/qemu-options.hx index 9ce8a5b95784..93e638c097bc 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4706,6 +4706,7 @@ DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \ " prepare for incoming migration, listen on\n" \ " specified protocol and socket address\n" \ "-incoming fd:fd\n" \ + "-incoming file:filename\n" \ "-incoming exec:cmdline\n" \ " accept incoming migration on given file descriptor\n" \ " or from given external command\n" \ @@ -4722,7 +4723,10 @@ SRST Prepare for incoming migration, listen on a given unix socket. ``-incoming fd:fd`` - Accept incoming migration from a given filedescriptor. + Accept incoming migration from a given file descriptor. + +``-incoming file:filename`` + Accept incoming migration from a given file. ``-incoming exec:cmdline`` Accept incoming migration as an output from specified external From 385f510df5f6a7f3998b3ff01deca33b0027ff29 Mon Sep 17 00:00:00 2001 From: Steve Sistare Date: Fri, 8 Sep 2023 07:22:11 -0700 Subject: [PATCH 203/208] migration: file URI offset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow an offset option to be specified as part of the file URI, in the form "file:filename,offset=offset", where offset accepts the common size suffixes, or the 0x prefix, but not both. Migration data is written to and read from the file starting at offset. If unspecified, it defaults to 0. This is needed by libvirt to store its own data at the head of the file. Suggested-by: Daniel P. Berrange Reviewed-by: Peter Xu Reviewed-by: Daniel P. Berrangé Reviewed-by: Juan Quintela Signed-off-by: Steve Sistare Signed-off-by: Juan Quintela Message-ID: <1694182931-61390-3-git-send-email-steven.sistare@oracle.com> --- migration/file.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- qemu-options.hx | 7 ++++--- 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/migration/file.c b/migration/file.c index 0a65c43fdd7c..cf5b1bf3656b 100644 --- a/migration/file.c +++ b/migration/file.c @@ -6,6 +6,8 @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" +#include "qapi/error.h" #include "channel.h" #include "file.h" #include "migration.h" @@ -13,14 +15,41 @@ #include "io/channel-util.h" #include "trace.h" -void file_start_outgoing_migration(MigrationState *s, const char *filename, +#define OFFSET_OPTION ",offset=" + +/* Remove the offset option from @filespec and return it in @offsetp. */ + +static int file_parse_offset(char *filespec, uint64_t *offsetp, Error **errp) +{ + char *option = strstr(filespec, OFFSET_OPTION); + int ret; + + if (option) { + *option = 0; + option += sizeof(OFFSET_OPTION) - 1; + ret = qemu_strtosz(option, NULL, offsetp); + if (ret) { + error_setg_errno(errp, -ret, "file URI has bad offset %s", option); + return -1; + } + } + return 0; +} + +void file_start_outgoing_migration(MigrationState *s, const char *filespec, Error **errp) { + g_autofree char *filename = g_strdup(filespec); g_autoptr(QIOChannelFile) fioc = NULL; + uint64_t offset = 0; QIOChannel *ioc; trace_migration_file_outgoing(filename); + if (file_parse_offset(filename, &offset, errp)) { + return; + } + fioc = qio_channel_file_new_path(filename, O_CREAT | O_WRONLY | O_TRUNC, 0600, errp); if (!fioc) { @@ -28,6 +57,9 @@ void file_start_outgoing_migration(MigrationState *s, const char *filename, } ioc = QIO_CHANNEL(fioc); + if (offset && qio_channel_io_seek(ioc, offset, SEEK_SET, errp) < 0) { + return; + } qio_channel_set_name(ioc, "migration-file-outgoing"); migration_channel_connect(s, ioc, NULL, NULL); } @@ -41,19 +73,28 @@ static gboolean file_accept_incoming_migration(QIOChannel *ioc, return G_SOURCE_REMOVE; } -void file_start_incoming_migration(const char *filename, Error **errp) +void file_start_incoming_migration(const char *filespec, Error **errp) { + g_autofree char *filename = g_strdup(filespec); QIOChannelFile *fioc = NULL; + uint64_t offset = 0; QIOChannel *ioc; trace_migration_file_incoming(filename); + if (file_parse_offset(filename, &offset, errp)) { + return; + } + fioc = qio_channel_file_new_path(filename, O_RDONLY, 0, errp); if (!fioc) { return; } ioc = QIO_CHANNEL(fioc); + if (offset && qio_channel_io_seek(ioc, offset, SEEK_SET, errp) < 0) { + return; + } qio_channel_set_name(QIO_CHANNEL(ioc), "migration-file-incoming"); qio_channel_add_watch_full(ioc, G_IO_IN, file_accept_incoming_migration, diff --git a/qemu-options.hx b/qemu-options.hx index 93e638c097bc..840b83d237aa 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4706,7 +4706,7 @@ DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \ " prepare for incoming migration, listen on\n" \ " specified protocol and socket address\n" \ "-incoming fd:fd\n" \ - "-incoming file:filename\n" \ + "-incoming file:filename[,offset=offset]\n" \ "-incoming exec:cmdline\n" \ " accept incoming migration on given file descriptor\n" \ " or from given external command\n" \ @@ -4725,8 +4725,9 @@ SRST ``-incoming fd:fd`` Accept incoming migration from a given file descriptor. -``-incoming file:filename`` - Accept incoming migration from a given file. +``-incoming file:filename[,offset=offset]`` + Accept incoming migration from a given file starting at offset. + offset allows the common size suffixes, or a 0x prefix, but not both. ``-incoming exec:cmdline`` Accept incoming migration as an output from specified external From 579cedf430582b37f804f6b6ed131554cebb11b5 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Wed, 6 Sep 2023 16:47:22 -0400 Subject: [PATCH 204/208] migration: Unify and trace vmstate field_exists() checks For both save/load we actually share the logic on deciding whether a field should exist. Merge the checks into a helper and use it for both save and load. When doing so, add documentations and reformat the code to make it much easier to read. The real benefit here (besides code cleanups) is we add a trace-point for this; this is a known spot where we can easily break migration compatibilities between binaries, and this trace point will be critical for us to identify such issues. For example, this will be handy when debugging things like: https://gitlab.com/qemu-project/qemu/-/issues/932 Reviewed-by: Fabiano Rosas Reviewed-by: Juan Quintela Signed-off-by: Peter Xu Signed-off-by: Juan Quintela Message-ID: <20230906204722.514474-1-peterx@redhat.com> --- migration/trace-events | 1 + migration/vmstate.c | 34 ++++++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/migration/trace-events b/migration/trace-events index 3e9649ab2a71..002abe3a4e95 100644 --- a/migration/trace-events +++ b/migration/trace-events @@ -66,6 +66,7 @@ vmstate_save_state_loop(const char *name, const char *field, int n_elems) "%s/%s vmstate_save_state_top(const char *idstr) "%s" vmstate_subsection_save_loop(const char *name, const char *sub) "%s/%s" vmstate_subsection_save_top(const char *idstr) "%s" +vmstate_field_exists(const char *vmsd, const char *name, int field_version, int version, int result) "%s:%s field_version %d version %d result %d" # vmstate-types.c get_qtailq(const char *name, int version_id) "%s v%d" diff --git a/migration/vmstate.c b/migration/vmstate.c index 4cde30bf2d9e..1cf9e45b85ac 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -26,6 +26,30 @@ static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, void *opaque); +/* Whether this field should exist for either save or load the VM? */ +static bool +vmstate_field_exists(const VMStateDescription *vmsd, const VMStateField *field, + void *opaque, int version_id) +{ + bool result; + + if (field->field_exists) { + /* If there's the function checker, that's the solo truth */ + result = field->field_exists(opaque, version_id); + trace_vmstate_field_exists(vmsd->name, field->name, field->version_id, + version_id, result); + } else { + /* + * Otherwise, we only save/load if field version is same or older. + * For example, when loading from an old binary with old version, + * we ignore new fields with newer version_ids. + */ + result = field->version_id <= version_id; + } + + return result; +} + static int vmstate_n_elems(void *opaque, const VMStateField *field) { int n_elems = 1; @@ -105,10 +129,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, } while (field->name) { trace_vmstate_load_state_field(vmsd->name, field->name); - if ((field->field_exists && - field->field_exists(opaque, version_id)) || - (!field->field_exists && - field->version_id <= version_id)) { + if (vmstate_field_exists(vmsd, field, opaque, version_id)) { void *first_elem = opaque + field->offset; int i, n_elems = vmstate_n_elems(opaque, field); int size = vmstate_size(opaque, field); @@ -349,10 +370,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd, } while (field->name) { - if ((field->field_exists && - field->field_exists(opaque, version_id)) || - (!field->field_exists && - field->version_id <= version_id)) { + if (vmstate_field_exists(vmsd, field, opaque, version_id)) { void *first_elem = opaque + field->offset; int i, n_elems = vmstate_n_elems(opaque, field); int size = vmstate_size(opaque, field); From 9afa888ce0f816d0f2cfc95eebe4f49244c518af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Tue, 3 Oct 2023 10:15:49 +0100 Subject: [PATCH 205/208] osdep: set _FORTIFY_SOURCE=2 when optimization is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we set _FORTIFY_SOURCE=2 as a compiler argument when the meson 'optimization' setting is non-zero, the compiler is GCC and the target is Linux. While the default QEMU optimization level is 2, user could override this by setting CFLAGS="-O0" or --extra-cflags="-O0" when running configure and this won't be reflected in the meson 'optimization' setting. As a result we try to enable _FORTIFY_SOURCE=2 and then the user gets compile errors as it only works with optimization. Rather than trying to improve detection in meson, it is simpler to just check the __OPTIMIZE__ define from osdep.h. The comment about being incompatible with clang appears to be outdated, as compilation works fine without excluding clang. In the coroutine code we must set _FORTIFY_SOURCE=0 to stop the logic in osdep.h then enabling it. Signed-off-by: Daniel P. Berrangé Message-id: 20231003091549.223020-1-berrange@redhat.com Signed-off-by: Stefan Hajnoczi --- include/qemu/osdep.h | 4 ++++ meson.build | 10 ---------- util/coroutine-sigaltstack.c | 4 ++-- util/coroutine-ucontext.c | 4 ++-- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 18b940db7585..475a1c62ff94 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -27,6 +27,10 @@ #ifndef QEMU_OSDEP_H #define QEMU_OSDEP_H +#if !defined _FORTIFY_SOURCE && defined __OPTIMIZE__ && __OPTIMIZE__ && defined __linux__ +# define _FORTIFY_SOURCE 2 +#endif + #include "config-host.h" #ifdef NEED_CPU_H #include CONFIG_TARGET diff --git a/meson.build b/meson.build index 21a1bc03f87e..20ceeb815826 100644 --- a/meson.build +++ b/meson.build @@ -479,16 +479,6 @@ if 'cpp' in all_languages qemu_cxxflags = ['-D__STDC_LIMIT_MACROS', '-D__STDC_CONSTANT_MACROS', '-D__STDC_FORMAT_MACROS'] + qemu_cflags endif -# clang does not support glibc + FORTIFY_SOURCE (is it still true?) -if get_option('optimization') != '0' and targetos == 'linux' - if cc.get_id() == 'gcc' - qemu_cflags += ['-U_FORTIFY_SOURCE', '-D_FORTIFY_SOURCE=2'] - endif - if 'cpp' in all_languages and cxx.get_id() == 'gcc' - qemu_cxxflags += ['-U_FORTIFY_SOURCE', '-D_FORTIFY_SOURCE=2'] - endif -endif - add_project_arguments(qemu_cflags, native: false, language: 'c') add_project_arguments(cc.get_supported_arguments(warn_flags), native: false, language: 'c') if 'cpp' in all_languages diff --git a/util/coroutine-sigaltstack.c b/util/coroutine-sigaltstack.c index e2690c5f4142..037d6416c4ae 100644 --- a/util/coroutine-sigaltstack.c +++ b/util/coroutine-sigaltstack.c @@ -22,9 +22,9 @@ */ /* XXX Is there a nicer way to disable glibc's stack check for longjmp? */ -#ifdef _FORTIFY_SOURCE #undef _FORTIFY_SOURCE -#endif +#define _FORTIFY_SOURCE 0 + #include "qemu/osdep.h" #include #include "qemu/coroutine_int.h" diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c index ddc98fb4f88c..7b304c79d942 100644 --- a/util/coroutine-ucontext.c +++ b/util/coroutine-ucontext.c @@ -19,9 +19,9 @@ */ /* XXX Is there a nicer way to disable glibc's stack check for longjmp? */ -#ifdef _FORTIFY_SOURCE #undef _FORTIFY_SOURCE -#endif +#define _FORTIFY_SOURCE 0 + #include "qemu/osdep.h" #include #include "qemu/coroutine_int.h" From 4b64ad4bc95b30c9abb62c947dfda90904156aeb Mon Sep 17 00:00:00 2001 From: Matheus Tavares Bernardino Date: Tue, 11 Jul 2023 07:17:48 -0300 Subject: [PATCH 206/208] target/hexagon: move GETPC() calls to top level helpers As docs/devel/loads-stores.rst states: ``GETPC()`` should be used with great care: calling it in other functions that are *not* the top level ``HELPER(foo)`` will cause unexpected behavior. Instead, the value of ``GETPC()`` should be read from the helper and passed if needed to the functions that the helper calls. Let's fix the GETPC() usage in Hexagon, making sure it's always called from top level helpers and passed down to the places where it's needed. There are a few snippets where that is not currently the case: - probe_store(), which is only called from two helpers, so it's easy to move GETPC() up. - mem_load*() functions, which are also called directly from helpers, but through the MEM_LOAD*() set of macros. Note that this are only used when compiling with --disable-hexagon-idef-parser. In this case, we also take this opportunity to simplify the code, unifying the mem_load*() functions. - HELPER(probe_hvx_stores), when called from another helper, ends up using its own GETPC() expansion instead of the top level caller. Signed-off-by: Matheus Tavares Bernardino Reviewed-by: Taylor Simpson Message-Id: <2c74c3696946edba7cc5b2942cf296a5af532052.1689070412.git.quic_mathbern@quicinc.com>-ne Reviewed-by: Brian Cain --- target/hexagon/macros.h | 19 +++++----- target/hexagon/op_helper.c | 75 +++++++++++++++----------------------- target/hexagon/op_helper.h | 9 ----- 3 files changed, 38 insertions(+), 65 deletions(-) diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h index 5451b061eef6..dafa0df6ed56 100644 --- a/target/hexagon/macros.h +++ b/target/hexagon/macros.h @@ -173,15 +173,6 @@ #define MEM_STORE8(VA, DATA, SLOT) \ MEM_STORE8_FUNC(DATA)(cpu_env, VA, DATA, SLOT) #else -#define MEM_LOAD1s(VA) ((int8_t)mem_load1(env, pkt_has_store_s1, slot, VA)) -#define MEM_LOAD1u(VA) ((uint8_t)mem_load1(env, pkt_has_store_s1, slot, VA)) -#define MEM_LOAD2s(VA) ((int16_t)mem_load2(env, pkt_has_store_s1, slot, VA)) -#define MEM_LOAD2u(VA) ((uint16_t)mem_load2(env, pkt_has_store_s1, slot, VA)) -#define MEM_LOAD4s(VA) ((int32_t)mem_load4(env, pkt_has_store_s1, slot, VA)) -#define MEM_LOAD4u(VA) ((uint32_t)mem_load4(env, pkt_has_store_s1, slot, VA)) -#define MEM_LOAD8s(VA) ((int64_t)mem_load8(env, pkt_has_store_s1, slot, VA)) -#define MEM_LOAD8u(VA) ((uint64_t)mem_load8(env, pkt_has_store_s1, slot, VA)) - #define MEM_STORE1(VA, DATA, SLOT) log_store32(env, VA, DATA, 1, SLOT) #define MEM_STORE2(VA, DATA, SLOT) log_store32(env, VA, DATA, 2, SLOT) #define MEM_STORE4(VA, DATA, SLOT) log_store32(env, VA, DATA, 4, SLOT) @@ -530,8 +521,16 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift) #ifdef QEMU_GENERATE #define fLOAD(NUM, SIZE, SIGN, EA, DST) MEM_LOAD##SIZE##SIGN(DST, EA) #else +#define MEM_LOAD1 cpu_ldub_data_ra +#define MEM_LOAD2 cpu_lduw_data_ra +#define MEM_LOAD4 cpu_ldl_data_ra +#define MEM_LOAD8 cpu_ldq_data_ra + #define fLOAD(NUM, SIZE, SIGN, EA, DST) \ - DST = (size##SIZE##SIGN##_t)MEM_LOAD##SIZE##SIGN(EA) + do { \ + check_noshuf(env, pkt_has_store_s1, slot, EA, SIZE, GETPC()); \ + DST = (size##SIZE##SIGN##_t)MEM_LOAD##SIZE(env, EA, GETPC()); \ + } while (0) #endif #define fMEMOP(NUM, SIZE, SIGN, EA, FNTYPE, VALUE) diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c index 12967ac21e03..8ca3976a65a1 100644 --- a/target/hexagon/op_helper.c +++ b/target/hexagon/op_helper.c @@ -95,9 +95,8 @@ void HELPER(debug_check_store_width)(CPUHexagonState *env, int slot, int check) } } -void HELPER(commit_store)(CPUHexagonState *env, int slot_num) +static void commit_store(CPUHexagonState *env, int slot_num, uintptr_t ra) { - uintptr_t ra = GETPC(); uint8_t width = env->mem_log_stores[slot_num].width; target_ulong va = env->mem_log_stores[slot_num].va; @@ -119,6 +118,12 @@ void HELPER(commit_store)(CPUHexagonState *env, int slot_num) } } +void HELPER(commit_store)(CPUHexagonState *env, int slot_num) +{ + uintptr_t ra = GETPC(); + commit_store(env, slot_num, ra); +} + void HELPER(gather_store)(CPUHexagonState *env, uint32_t addr, int slot) { mem_gather_store(env, addr, slot); @@ -467,13 +472,12 @@ int32_t HELPER(cabacdecbin_pred)(int64_t RssV, int64_t RttV) } static void probe_store(CPUHexagonState *env, int slot, int mmu_idx, - bool is_predicated) + bool is_predicated, uintptr_t retaddr) { if (!is_predicated || !(env->slot_cancelled & (1 << slot))) { size1u_t width = env->mem_log_stores[slot].width; target_ulong va = env->mem_log_stores[slot].va; - uintptr_t ra = GETPC(); - probe_write(env, va, width, mmu_idx, ra); + probe_write(env, va, width, mmu_idx, retaddr); } } @@ -494,12 +498,13 @@ void HELPER(probe_pkt_scalar_store_s0)(CPUHexagonState *env, int args) int mmu_idx = FIELD_EX32(args, PROBE_PKT_SCALAR_STORE_S0, MMU_IDX); bool is_predicated = FIELD_EX32(args, PROBE_PKT_SCALAR_STORE_S0, IS_PREDICATED); - probe_store(env, 0, mmu_idx, is_predicated); + uintptr_t ra = GETPC(); + probe_store(env, 0, mmu_idx, is_predicated, ra); } -void HELPER(probe_hvx_stores)(CPUHexagonState *env, int mmu_idx) +static void probe_hvx_stores(CPUHexagonState *env, int mmu_idx, + uintptr_t retaddr) { - uintptr_t retaddr = GETPC(); int i; /* Normal (possibly masked) vector store */ @@ -538,6 +543,12 @@ void HELPER(probe_hvx_stores)(CPUHexagonState *env, int mmu_idx) } } +void HELPER(probe_hvx_stores)(CPUHexagonState *env, int mmu_idx) +{ + uintptr_t retaddr = GETPC(); + probe_hvx_stores(env, mmu_idx, retaddr); +} + void HELPER(probe_pkt_scalar_hvx_stores)(CPUHexagonState *env, int mask) { bool has_st0 = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_ST0); @@ -547,18 +558,20 @@ void HELPER(probe_pkt_scalar_hvx_stores)(CPUHexagonState *env, int mask) bool s0_is_pred = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, S0_IS_PRED); bool s1_is_pred = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, S1_IS_PRED); int mmu_idx = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, MMU_IDX); + uintptr_t ra = GETPC(); if (has_st0) { - probe_store(env, 0, mmu_idx, s0_is_pred); + probe_store(env, 0, mmu_idx, s0_is_pred, ra); } if (has_st1) { - probe_store(env, 1, mmu_idx, s1_is_pred); + probe_store(env, 1, mmu_idx, s1_is_pred, ra); } if (has_hvx_stores) { - HELPER(probe_hvx_stores)(env, mmu_idx); + probe_hvx_stores(env, mmu_idx, ra); } } +#ifndef CONFIG_HEXAGON_IDEF_PARSER /* * mem_noshuf * Section 5.5 of the Hexagon V67 Programmer's Reference Manual @@ -567,46 +580,16 @@ void HELPER(probe_pkt_scalar_hvx_stores)(CPUHexagonState *env, int mask) * wasn't cancelled), we have to do the store first. */ static void check_noshuf(CPUHexagonState *env, bool pkt_has_store_s1, - uint32_t slot, target_ulong vaddr, int size) + uint32_t slot, target_ulong vaddr, int size, + uintptr_t ra) { if (slot == 0 && pkt_has_store_s1 && ((env->slot_cancelled & (1 << 1)) == 0)) { - HELPER(probe_noshuf_load)(env, vaddr, size, MMU_USER_IDX); - HELPER(commit_store)(env, 1); + probe_read(env, vaddr, size, MMU_USER_IDX, ra); + commit_store(env, 1, ra); } } - -uint8_t mem_load1(CPUHexagonState *env, bool pkt_has_store_s1, - uint32_t slot, target_ulong vaddr) -{ - uintptr_t ra = GETPC(); - check_noshuf(env, pkt_has_store_s1, slot, vaddr, 1); - return cpu_ldub_data_ra(env, vaddr, ra); -} - -uint16_t mem_load2(CPUHexagonState *env, bool pkt_has_store_s1, - uint32_t slot, target_ulong vaddr) -{ - uintptr_t ra = GETPC(); - check_noshuf(env, pkt_has_store_s1, slot, vaddr, 2); - return cpu_lduw_data_ra(env, vaddr, ra); -} - -uint32_t mem_load4(CPUHexagonState *env, bool pkt_has_store_s1, - uint32_t slot, target_ulong vaddr) -{ - uintptr_t ra = GETPC(); - check_noshuf(env, pkt_has_store_s1, slot, vaddr, 4); - return cpu_ldl_data_ra(env, vaddr, ra); -} - -uint64_t mem_load8(CPUHexagonState *env, bool pkt_has_store_s1, - uint32_t slot, target_ulong vaddr) -{ - uintptr_t ra = GETPC(); - check_noshuf(env, pkt_has_store_s1, slot, vaddr, 8); - return cpu_ldq_data_ra(env, vaddr, ra); -} +#endif /* Floating point */ float64 HELPER(conv_sf2df)(CPUHexagonState *env, float32 RsV) diff --git a/target/hexagon/op_helper.h b/target/hexagon/op_helper.h index 8f3764d15ee2..66119cf3d4ce 100644 --- a/target/hexagon/op_helper.h +++ b/target/hexagon/op_helper.h @@ -19,15 +19,6 @@ #define HEXAGON_OP_HELPER_H /* Misc functions */ -uint8_t mem_load1(CPUHexagonState *env, bool pkt_has_store_s1, - uint32_t slot, target_ulong vaddr); -uint16_t mem_load2(CPUHexagonState *env, bool pkt_has_store_s1, - uint32_t slot, target_ulong vaddr); -uint32_t mem_load4(CPUHexagonState *env, bool pkt_has_store_s1, - uint32_t slot, target_ulong vaddr); -uint64_t mem_load8(CPUHexagonState *env, bool pkt_has_store_s1, - uint32_t slot, target_ulong vaddr); - void log_store64(CPUHexagonState *env, target_ulong addr, int64_t val, int width, int slot); void log_store32(CPUHexagonState *env, target_ulong addr, From a5bc4c212361bde63a52b655b6b263ffa409bdf8 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Thu, 28 Sep 2023 07:45:57 -0700 Subject: [PATCH 207/208] target/hexagon: fix some occurrences of -Wshadow=local MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Of the changes in this commit, the changes in `HELPER(commit_hvx_stores)()` are less obvious. They are required because of some macro invocations like SCATTER_OP_WRITE_TO_MEM(). e.g.: In file included from ../target/hexagon/op_helper.c:31: ../target/hexagon/mmvec/macros.h:205:18: error: declaration of ‘i’ shadows a previous local [-Werror=shadow=compatible-local] 205 | for (int i = 0; i < sizeof(MMVector); i += sizeof(TYPE)) { \ | ^ ../target/hexagon/op_helper.c:157:17: note: in expansion of macro ‘SCATTER_OP_WRITE_TO_MEM’ 157 | SCATTER_OP_WRITE_TO_MEM(uint16_t); | ^~~~~~~~~~~~~~~~~~~~~~~ ../target/hexagon/op_helper.c:135:9: note: shadowed declaration is here 135 | int i; | ^ In file included from ../target/hexagon/op_helper.c:31: ../target/hexagon/mmvec/macros.h:204:19: error: declaration of ‘ra’ shadows a previous local [-Werror=shadow=compatible-local] 204 | uintptr_t ra = GETPC(); \ | ^~ ../target/hexagon/op_helper.c:160:17: note: in expansion of macro ‘SCATTER_OP_WRITE_TO_MEM’ 160 | SCATTER_OP_WRITE_TO_MEM(uint32_t); | ^~~~~~~~~~~~~~~~~~~~~~~ ../target/hexagon/op_helper.c:134:15: note: shadowed declaration is here 134 | uintptr_t ra = GETPC(); | ^~ Reviewed-by: Matheus Tavares Bernardino Signed-off-by: Brian Cain --- target/hexagon/imported/alu.idef | 6 +++--- target/hexagon/mmvec/macros.h | 2 +- target/hexagon/op_helper.c | 9 +++------ target/hexagon/translate.c | 10 +++++----- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/target/hexagon/imported/alu.idef b/target/hexagon/imported/alu.idef index 12d2aac5d4c3..b8556769891b 100644 --- a/target/hexagon/imported/alu.idef +++ b/target/hexagon/imported/alu.idef @@ -1142,9 +1142,9 @@ Q6INSN(A4_cround_rr,"Rd32=cround(Rs32,Rt32)",ATTRIBS(),"Convergent Round", {RdV tmp128 = fSHIFTR128(tmp128, SHIFT);\ DST = fCAST16S_8S(tmp128);\ } else {\ - size16s_t rndbit_128 = fCAST8S_16S((1LL << (SHIFT - 1))); \ - size16s_t src_128 = fCAST8S_16S(SRC); \ - size16s_t tmp128 = fADD128(src_128, rndbit_128);\ + rndbit_128 = fCAST8S_16S((1LL << (SHIFT - 1))); \ + src_128 = fCAST8S_16S(SRC); \ + tmp128 = fADD128(src_128, rndbit_128);\ tmp128 = fSHIFTR128(tmp128, SHIFT);\ DST = fCAST16S_8S(tmp128);\ } diff --git a/target/hexagon/mmvec/macros.h b/target/hexagon/mmvec/macros.h index a655634fd158..1ceb9453ee4e 100644 --- a/target/hexagon/mmvec/macros.h +++ b/target/hexagon/mmvec/macros.h @@ -201,7 +201,7 @@ } while (0) #define SCATTER_OP_WRITE_TO_MEM(TYPE) \ do { \ - uintptr_t ra = GETPC(); \ + ra = GETPC(); \ for (int i = 0; i < sizeof(MMVector); i += sizeof(TYPE)) { \ if (test_bit(i, env->vtcm_log.mask)) { \ TYPE dst = 0; \ diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c index 8ca3976a65a1..da10ac584769 100644 --- a/target/hexagon/op_helper.c +++ b/target/hexagon/op_helper.c @@ -132,10 +132,9 @@ void HELPER(gather_store)(CPUHexagonState *env, uint32_t addr, int slot) void HELPER(commit_hvx_stores)(CPUHexagonState *env) { uintptr_t ra = GETPC(); - int i; /* Normal (possibly masked) vector store */ - for (i = 0; i < VSTORES_MAX; i++) { + for (int i = 0; i < VSTORES_MAX; i++) { if (env->vstore_pending[i]) { env->vstore_pending[i] = 0; target_ulong va = env->vstore[i].va; @@ -162,7 +161,7 @@ void HELPER(commit_hvx_stores)(CPUHexagonState *env) g_assert_not_reached(); } } else { - for (i = 0; i < sizeof(MMVector); i++) { + for (int i = 0; i < sizeof(MMVector); i++) { if (test_bit(i, env->vtcm_log.mask)) { cpu_stb_data_ra(env, env->vtcm_log.va[i], env->vtcm_log.data.ub[i], ra); @@ -505,10 +504,8 @@ void HELPER(probe_pkt_scalar_store_s0)(CPUHexagonState *env, int args) static void probe_hvx_stores(CPUHexagonState *env, int mmu_idx, uintptr_t retaddr) { - int i; - /* Normal (possibly masked) vector store */ - for (i = 0; i < VSTORES_MAX; i++) { + for (int i = 0; i < VSTORES_MAX; i++) { if (env->vstore_pending[i]) { target_ulong va = env->vstore[i].va; int size = env->vstore[i].size; diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index c00254e4d5b7..a1c7cd6f21d1 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -553,7 +553,7 @@ static void gen_start_packet(DisasContext *ctx) /* Preload the predicated registers into get_result_gpr(ctx, i) */ if (ctx->need_commit && !bitmap_empty(ctx->predicated_regs, TOTAL_PER_THREAD_REGS)) { - int i = find_first_bit(ctx->predicated_regs, TOTAL_PER_THREAD_REGS); + i = find_first_bit(ctx->predicated_regs, TOTAL_PER_THREAD_REGS); while (i < TOTAL_PER_THREAD_REGS) { tcg_gen_mov_tl(get_result_gpr(ctx, i), hex_gpr[i]); i = find_next_bit(ctx->predicated_regs, TOTAL_PER_THREAD_REGS, @@ -566,7 +566,7 @@ static void gen_start_packet(DisasContext *ctx) * Only endloop instructions conditionally write to pred registers */ if (ctx->need_commit && pkt->pkt_has_endloop) { - for (int i = 0; i < ctx->preg_log_idx; i++) { + for (i = 0; i < ctx->preg_log_idx; i++) { int pred_num = ctx->preg_log[i]; ctx->new_pred_value[pred_num] = tcg_temp_new(); tcg_gen_mov_tl(ctx->new_pred_value[pred_num], hex_pred[pred_num]); @@ -575,7 +575,7 @@ static void gen_start_packet(DisasContext *ctx) /* Preload the predicated HVX registers into future_VRegs and tmp_VRegs */ if (!bitmap_empty(ctx->predicated_future_vregs, NUM_VREGS)) { - int i = find_first_bit(ctx->predicated_future_vregs, NUM_VREGS); + i = find_first_bit(ctx->predicated_future_vregs, NUM_VREGS); while (i < NUM_VREGS) { const intptr_t VdV_off = ctx_future_vreg_off(ctx, i, 1, true); @@ -588,7 +588,7 @@ static void gen_start_packet(DisasContext *ctx) } } if (!bitmap_empty(ctx->predicated_tmp_vregs, NUM_VREGS)) { - int i = find_first_bit(ctx->predicated_tmp_vregs, NUM_VREGS); + i = find_first_bit(ctx->predicated_tmp_vregs, NUM_VREGS); while (i < NUM_VREGS) { const intptr_t VdV_off = ctx_tmp_vreg_off(ctx, i, 1, true); @@ -1228,7 +1228,7 @@ void hexagon_translate_init(void) offsetof(CPUHexagonState, mem_log_stores[i].data64), store_val64_names[i]); } - for (int i = 0; i < VSTORES_MAX; i++) { + for (i = 0; i < VSTORES_MAX; i++) { snprintf(vstore_addr_names[i], NAME_LEN, "vstore_addr_%d", i); hex_vstore_addr[i] = tcg_global_mem_new(cpu_env, offsetof(CPUHexagonState, vstore[i].va), From 28a2c4cec84ff5744b8b5dec5bcfa9548f82dea7 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 4 Oct 2023 20:03:51 -0700 Subject: [PATCH 208/208] target/hexagon: avoid shadowing "vaddr" type The typedef `vaddr` is shadowed by `vaddr` identifiers, so we rename the identifiers to avoid shadowing the type name. Signed-off-by: Brian Cain --- target/hexagon/genptr.c | 56 ++++++++++++------------- target/hexagon/mmvec/system_ext_mmvec.c | 4 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c index 217bc7bb5a2c..78d0dab4af52 100644 --- a/target/hexagon/genptr.c +++ b/target/hexagon/genptr.c @@ -334,28 +334,28 @@ void gen_set_byte_i64(int N, TCGv_i64 result, TCGv src) tcg_gen_deposit_i64(result, result, src64, N * 8, 8); } -static inline void gen_load_locked4u(TCGv dest, TCGv vaddr, int mem_index) +static inline void gen_load_locked4u(TCGv dest, TCGv v_addr, int mem_index) { - tcg_gen_qemu_ld_tl(dest, vaddr, mem_index, MO_TEUL); - tcg_gen_mov_tl(hex_llsc_addr, vaddr); + tcg_gen_qemu_ld_tl(dest, v_addr, mem_index, MO_TEUL); + tcg_gen_mov_tl(hex_llsc_addr, v_addr); tcg_gen_mov_tl(hex_llsc_val, dest); } -static inline void gen_load_locked8u(TCGv_i64 dest, TCGv vaddr, int mem_index) +static inline void gen_load_locked8u(TCGv_i64 dest, TCGv v_addr, int mem_index) { - tcg_gen_qemu_ld_i64(dest, vaddr, mem_index, MO_TEUQ); - tcg_gen_mov_tl(hex_llsc_addr, vaddr); + tcg_gen_qemu_ld_i64(dest, v_addr, mem_index, MO_TEUQ); + tcg_gen_mov_tl(hex_llsc_addr, v_addr); tcg_gen_mov_i64(hex_llsc_val_i64, dest); } static inline void gen_store_conditional4(DisasContext *ctx, - TCGv pred, TCGv vaddr, TCGv src) + TCGv pred, TCGv v_addr, TCGv src) { TCGLabel *fail = gen_new_label(); TCGLabel *done = gen_new_label(); TCGv one, zero, tmp; - tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail); + tcg_gen_brcond_tl(TCG_COND_NE, v_addr, hex_llsc_addr, fail); one = tcg_constant_tl(0xff); zero = tcg_constant_tl(0); @@ -374,13 +374,13 @@ static inline void gen_store_conditional4(DisasContext *ctx, } static inline void gen_store_conditional8(DisasContext *ctx, - TCGv pred, TCGv vaddr, TCGv_i64 src) + TCGv pred, TCGv v_addr, TCGv_i64 src) { TCGLabel *fail = gen_new_label(); TCGLabel *done = gen_new_label(); TCGv_i64 one, zero, tmp; - tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail); + tcg_gen_brcond_tl(TCG_COND_NE, v_addr, hex_llsc_addr, fail); one = tcg_constant_i64(0xff); zero = tcg_constant_i64(0); @@ -407,57 +407,57 @@ static TCGv gen_slotval(DisasContext *ctx) } #endif -void gen_store32(TCGv vaddr, TCGv src, int width, uint32_t slot) +void gen_store32(TCGv v_addr, TCGv src, int width, uint32_t slot) { - tcg_gen_mov_tl(hex_store_addr[slot], vaddr); + tcg_gen_mov_tl(hex_store_addr[slot], v_addr); tcg_gen_movi_tl(hex_store_width[slot], width); tcg_gen_mov_tl(hex_store_val32[slot], src); } -void gen_store1(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot) +void gen_store1(TCGv_env cpu_env, TCGv v_addr, TCGv src, uint32_t slot) { - gen_store32(vaddr, src, 1, slot); + gen_store32(v_addr, src, 1, slot); } -void gen_store1i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot) +void gen_store1i(TCGv_env cpu_env, TCGv v_addr, int32_t src, uint32_t slot) { TCGv tmp = tcg_constant_tl(src); - gen_store1(cpu_env, vaddr, tmp, slot); + gen_store1(cpu_env, v_addr, tmp, slot); } -void gen_store2(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot) +void gen_store2(TCGv_env cpu_env, TCGv v_addr, TCGv src, uint32_t slot) { - gen_store32(vaddr, src, 2, slot); + gen_store32(v_addr, src, 2, slot); } -void gen_store2i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot) +void gen_store2i(TCGv_env cpu_env, TCGv v_addr, int32_t src, uint32_t slot) { TCGv tmp = tcg_constant_tl(src); - gen_store2(cpu_env, vaddr, tmp, slot); + gen_store2(cpu_env, v_addr, tmp, slot); } -void gen_store4(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot) +void gen_store4(TCGv_env cpu_env, TCGv v_addr, TCGv src, uint32_t slot) { - gen_store32(vaddr, src, 4, slot); + gen_store32(v_addr, src, 4, slot); } -void gen_store4i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot) +void gen_store4i(TCGv_env cpu_env, TCGv v_addr, int32_t src, uint32_t slot) { TCGv tmp = tcg_constant_tl(src); - gen_store4(cpu_env, vaddr, tmp, slot); + gen_store4(cpu_env, v_addr, tmp, slot); } -void gen_store8(TCGv_env cpu_env, TCGv vaddr, TCGv_i64 src, uint32_t slot) +void gen_store8(TCGv_env cpu_env, TCGv v_addr, TCGv_i64 src, uint32_t slot) { - tcg_gen_mov_tl(hex_store_addr[slot], vaddr); + tcg_gen_mov_tl(hex_store_addr[slot], v_addr); tcg_gen_movi_tl(hex_store_width[slot], 8); tcg_gen_mov_i64(hex_store_val64[slot], src); } -void gen_store8i(TCGv_env cpu_env, TCGv vaddr, int64_t src, uint32_t slot) +void gen_store8i(TCGv_env cpu_env, TCGv v_addr, int64_t src, uint32_t slot) { TCGv_i64 tmp = tcg_constant_i64(src); - gen_store8(cpu_env, vaddr, tmp, slot); + gen_store8(cpu_env, v_addr, tmp, slot); } TCGv gen_8bitsof(TCGv result, TCGv value) diff --git a/target/hexagon/mmvec/system_ext_mmvec.c b/target/hexagon/mmvec/system_ext_mmvec.c index 8351f2cc01bf..c339eee38bcd 100644 --- a/target/hexagon/mmvec/system_ext_mmvec.c +++ b/target/hexagon/mmvec/system_ext_mmvec.c @@ -19,12 +19,12 @@ #include "cpu.h" #include "mmvec/system_ext_mmvec.h" -void mem_gather_store(CPUHexagonState *env, target_ulong vaddr, int slot) +void mem_gather_store(CPUHexagonState *env, target_ulong v_addr, int slot) { size_t size = sizeof(MMVector); env->vstore_pending[slot] = 1; - env->vstore[slot].va = vaddr; + env->vstore[slot].va = v_addr; env->vstore[slot].size = size; memcpy(&env->vstore[slot].data.ub[0], &env->tmp_VRegs[0], size);