summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/acpi_extract.py23
-rwxr-xr-xscripts/checkpatch.pl8
-rwxr-xr-xscripts/cleanup-trace-events.pl2
-rwxr-xr-xscripts/get_maintainer.pl28
-rwxr-xr-xscripts/kvm/kvm_stat150
-rwxr-xr-xscripts/kvm/vmxcap10
-rw-r--r--scripts/qapi-types.py2
-rw-r--r--scripts/qapi-visit.py9
-rw-r--r--scripts/qapi.py8
-rwxr-xr-xscripts/qtest5
-rwxr-xr-xscripts/simpletrace.py24
-rw-r--r--scripts/tracetool/__init__.py109
-rw-r--r--scripts/tracetool/backend/__init__.py3
-rw-r--r--scripts/tracetool/format/events_h.py5
-rw-r--r--scripts/tracetool/format/simpletrace_stap.py71
-rw-r--r--scripts/tracetool/format/stap.py11
-rw-r--r--scripts/tracetool/format/tcg_h.py57
-rw-r--r--scripts/tracetool/format/tcg_helper_c.py50
-rw-r--r--scripts/tracetool/format/tcg_helper_h.py50
-rw-r--r--scripts/tracetool/format/tcg_helper_wrapper_h.py70
-rw-r--r--scripts/tracetool/format/ust_events_h.py15
-rw-r--r--scripts/tracetool/transform.py166
-rwxr-xr-xscripts/vmstate-static-checker.py70
23 files changed, 830 insertions, 116 deletions
diff --git a/scripts/acpi_extract.py b/scripts/acpi_extract.py
index 22ea46810..10c1ffb36 100755
--- a/scripts/acpi_extract.py
+++ b/scripts/acpi_extract.py
@@ -139,13 +139,16 @@ def aml_name_string(offset):
offset += 1
return offset;
-# Given data offset, find 8 byte buffer offset
-def aml_data_buffer8(offset):
- #0x08 NameOp NameString DataRef
- expect = [0x11, 0x0B, 0x0A, 0x08]
+# Given data offset, find variable length byte buffer offset
+def aml_data_buffer(offset, length):
+ #0x11 PkgLength BufferSize ByteList
+ if (length > 63):
+ die( "Name offset 0x%x: expected a one byte PkgLength (length<=63)" %
+ (offset));
+ expect = [0x11, length+3, 0x0A, length]
if (aml[offset:offset+4] != expect):
die( "Name offset 0x%x: expected %s actual %s" %
- (offset, aml[offset:offset+4], expect))
+ (offset, expect, aml[offset:offset+4]))
return offset + len(expect)
# Given data offset, find dword const offset
@@ -172,9 +175,9 @@ def aml_data_byte_const(offset):
(offset, aml[offset]));
return offset + 1;
-# Find name'd buffer8
-def aml_name_buffer8(offset):
- return aml_data_buffer8(aml_name_string(offset) + 4)
+# Find name'd buffer
+def aml_name_buffer(offset, length):
+ return aml_data_buffer(aml_name_string(offset) + 4, length)
# Given name offset, find dword const offset
def aml_name_dword_const(offset):
@@ -308,7 +311,9 @@ for i in range(len(asl)):
output[array] = aml
continue
if (directive == "ACPI_EXTRACT_NAME_BUFFER8"):
- offset = aml_name_buffer8(offset)
+ offset = aml_name_buffer(offset, 8)
+ elif (directive == "ACPI_EXTRACT_NAME_BUFFER16"):
+ offset = aml_name_buffer(offset, 16)
elif (directive == "ACPI_EXTRACT_NAME_DWORD_CONST"):
offset = aml_name_dword_const(offset)
elif (directive == "ACPI_EXTRACT_NAME_WORD_CONST"):
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 9d46e5a10..053e4320f 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -206,9 +206,13 @@ our $UTF8 = qr {
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
}x;
+# There are still some false positives, but this catches most
+# common cases.
our $typeTypedefs = qr{(?x:
- (?:__)?(?:u|s|be|le)(?:8|16|32|64)|
- atomic_t
+ [A-Z][A-Z\d_]*[a-z][A-Za-z\d_]* # camelcase
+ | [A-Z][A-Z\d_]*AIOCB # all uppercase
+ | [A-Z][A-Z\d_]*CPU # all uppercase
+ | QEMUBH # all uppercase
)};
our $logFunctions = qr{(?x:
diff --git a/scripts/cleanup-trace-events.pl b/scripts/cleanup-trace-events.pl
index cffbf165d..7e808efb6 100755
--- a/scripts/cleanup-trace-events.pl
+++ b/scripts/cleanup-trace-events.pl
@@ -25,7 +25,7 @@ sub out {
while (<>) {
if (/^(disable )?([a-z_0-9]+)\(/) {
- open GREP, '-|', 'git', 'grep', '-l', "trace_$2"
+ open GREP, '-|', 'git', 'grep', '-lw', "trace_$2"
or die "run git grep: $!";
my $fname;
while ($fname = <GREP>) {
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 38334de87..af68c6c92 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -651,18 +651,26 @@ sub get_maintainers {
$email->[0] = deduplicate_email($email->[0]);
}
- foreach my $file (@files) {
- if ($email &&
- ($email_git || ($email_git_fallback &&
- !$exact_pattern_match_hash{$file}))) {
- vcs_file_signoffs($file);
- }
- if ($email && $email_git_blame) {
- vcs_file_blame($file);
+ if ($email) {
+ if (! $interactive) {
+ $email_git_fallback = 0 if @email_to > 0 || @list_to > 0 || $email_git || $email_git_blame;
+ if ($email_git_fallback) {
+ print STDERR "get_maintainer.pl: No maintainers found, printing recent contributors.\n";
+ print STDERR "get_maintainer.pl: Do not blindly cc: them on patches! Use common sense.\n";
+ print STDERR "\n";
+ }
+ }
+
+ foreach my $file (@files) {
+ if ($email_git || ($email_git_fallback &&
+ !$exact_pattern_match_hash{$file})) {
+ vcs_file_signoffs($file);
+ }
+ if ($email_git_blame) {
+ vcs_file_blame($file);
+ }
}
- }
- if ($email) {
foreach my $chief (@penguin_chief) {
if ($chief =~ m/^(.*):(.*)/) {
my $email_address;
diff --git a/scripts/kvm/kvm_stat b/scripts/kvm/kvm_stat
index d7e97e748..7b1437ca2 100755
--- a/scripts/kvm/kvm_stat
+++ b/scripts/kvm/kvm_stat
@@ -12,7 +12,7 @@
# the COPYING file in the top-level directory.
import curses
-import sys, os, time, optparse
+import sys, os, time, optparse, ctypes
class DebugfsProvider(object):
def __init__(self):
@@ -141,61 +141,97 @@ svm_exit_reasons = {
0x400: 'NPF',
}
-s390_exit_reasons = {
- 0x000: 'UNKNOWN',
- 0x001: 'EXCEPTION',
- 0x002: 'IO',
- 0x003: 'HYPERCALL',
- 0x004: 'DEBUG',
- 0x005: 'HLT',
- 0x006: 'MMIO',
- 0x007: 'IRQ_WINDOW_OPEN',
- 0x008: 'SHUTDOWN',
- 0x009: 'FAIL_ENTRY',
- 0x010: 'INTR',
- 0x011: 'SET_TPR',
- 0x012: 'TPR_ACCESS',
- 0x013: 'S390_SIEIC',
- 0x014: 'S390_RESET',
- 0x015: 'DCR',
- 0x016: 'NMI',
- 0x017: 'INTERNAL_ERROR',
- 0x018: 'OSI',
- 0x019: 'PAPR_HCALL',
+# From include/uapi/linux/kvm.h, KVM_EXIT_xxx
+userspace_exit_reasons = {
+ 0: 'UNKNOWN',
+ 1: 'EXCEPTION',
+ 2: 'IO',
+ 3: 'HYPERCALL',
+ 4: 'DEBUG',
+ 5: 'HLT',
+ 6: 'MMIO',
+ 7: 'IRQ_WINDOW_OPEN',
+ 8: 'SHUTDOWN',
+ 9: 'FAIL_ENTRY',
+ 10: 'INTR',
+ 11: 'SET_TPR',
+ 12: 'TPR_ACCESS',
+ 13: 'S390_SIEIC',
+ 14: 'S390_RESET',
+ 15: 'DCR',
+ 16: 'NMI',
+ 17: 'INTERNAL_ERROR',
+ 18: 'OSI',
+ 19: 'PAPR_HCALL',
+ 20: 'S390_UCONTROL',
+ 21: 'WATCHDOG',
+ 22: 'S390_TSCH',
+ 23: 'EPR',
}
-vendor_exit_reasons = {
+x86_exit_reasons = {
'vmx': vmx_exit_reasons,
'svm': svm_exit_reasons,
- 'IBM/S390': s390_exit_reasons,
}
-syscall_numbers = {
- 'IBM/S390': 331,
-}
-
-sc_perf_evt_open = 298
-
+sc_perf_evt_open = None
exit_reasons = None
-for line in file('/proc/cpuinfo').readlines():
- if line.startswith('flags') or line.startswith('vendor_id'):
- for flag in line.split():
- if flag in vendor_exit_reasons:
- exit_reasons = vendor_exit_reasons[flag]
- if flag in syscall_numbers:
- sc_perf_evt_open = syscall_numbers[flag]
-filters = {
- 'kvm_exit': ('exit_reason', exit_reasons)
+ioctl_numbers = {
+ 'SET_FILTER' : 0x40082406,
+ 'ENABLE' : 0x00002400,
+ 'DISABLE' : 0x00002401,
}
+def x86_init(flag):
+ globals().update({
+ 'sc_perf_evt_open' : 298,
+ 'exit_reasons' : x86_exit_reasons[flag],
+ })
+
+def s390_init():
+ globals().update({
+ 'sc_perf_evt_open' : 331
+ })
+
+def ppc_init():
+ globals().update({
+ 'sc_perf_evt_open' : 319,
+ 'ioctl_numbers' : {
+ 'SET_FILTER' : 0x80002406 | (ctypes.sizeof(ctypes.c_char_p) << 16),
+ 'ENABLE' : 0x20002400,
+ 'DISABLE' : 0x20002401,
+ }
+ })
+
+def detect_platform():
+ if os.uname()[4].startswith('ppc'):
+ ppc_init()
+ return
+
+ for line in file('/proc/cpuinfo').readlines():
+ if line.startswith('flags'):
+ for flag in line.split():
+ if flag in x86_exit_reasons:
+ x86_init(flag)
+ return
+ elif line.startswith('vendor_id'):
+ for flag in line.split():
+ if flag == 'IBM/S390':
+ s390_init()
+ return
+
+detect_platform()
+
def invert(d):
return dict((x[1], x[0]) for x in d.iteritems())
-for f in filters:
- filters[f] = (filters[f][0], invert(filters[f][1]))
+filters = {}
+filters['kvm_userspace_exit'] = ('reason', invert(userspace_exit_reasons))
+if exit_reasons:
+ filters['kvm_exit'] = ('exit_reason', invert(exit_reasons))
-import ctypes, struct, array
+import struct, array
libc = ctypes.CDLL('libc.so.6')
syscall = libc.syscall
@@ -285,14 +321,14 @@ class Event(object):
raise Exception('perf_event_open failed')
if filter:
import fcntl
- fcntl.ioctl(fd, 0x40082406, filter)
+ fcntl.ioctl(fd, ioctl_numbers['SET_FILTER'], filter)
self.fd = fd
def enable(self):
import fcntl
- fcntl.ioctl(self.fd, 0x00002400, 0)
+ fcntl.ioctl(self.fd, ioctl_numbers['ENABLE'], 0)
def disable(self):
import fcntl
- fcntl.ioctl(self.fd, 0x00002401, 0)
+ fcntl.ioctl(self.fd, ioctl_numbers['DISABLE'], 0)
class TracepointProvider(object):
def __init__(self):
@@ -311,18 +347,30 @@ class TracepointProvider(object):
self.select(fields)
def fields(self):
return self._fields
+
+ def _online_cpus(self):
+ l = []
+ pattern = r'cpu([0-9]+)'
+ basedir = '/sys/devices/system/cpu'
+ for entry in os.listdir(basedir):
+ match = re.match(pattern, entry)
+ if not match:
+ continue
+ path = os.path.join(basedir, entry, 'online')
+ if os.path.exists(path) and open(path).read().strip() != '1':
+ continue
+ l.append(int(match.group(1)))
+ return l
+
def _setup(self, _fields):
self._fields = _fields
- cpure = r'cpu([0-9]+)'
- self.cpus = [int(re.match(cpure, x).group(1))
- for x in os.listdir('/sys/devices/system/cpu')
- if re.match(cpure, x)]
+ cpus = self._online_cpus()
import resource
- nfiles = len(self.cpus) * 1000
+ nfiles = len(cpus) * 1000
resource.setrlimit(resource.RLIMIT_NOFILE, (nfiles, nfiles))
events = []
self.group_leaders = []
- for cpu in self.cpus:
+ for cpu in cpus:
group = Group(cpu)
for name in _fields:
tracepoint = name
diff --git a/scripts/kvm/vmxcap b/scripts/kvm/vmxcap
index c90eda497..8f0371f49 100755
--- a/scripts/kvm/vmxcap
+++ b/scripts/kvm/vmxcap
@@ -99,7 +99,7 @@ controls = [
Misc(
name = 'Basic VMX Information',
bits = {
- (0, 31): 'Revision',
+ (0, 30): 'Revision',
(32,44): 'VMCS size',
48: 'VMCS restricted to 32 bit addresses',
49: 'Dual-monitor support',
@@ -169,7 +169,9 @@ controls = [
12: 'Enable INVPCID',
13: 'Enable VM functions',
14: 'VMCS shadowing',
- 18: 'EPT-violation #VE'
+ 16: 'RDSEED exiting',
+ 18: 'EPT-violation #VE',
+ 20: 'Enable XSAVES/XRSTORS',
},
cap_msr = MSR_IA32_VMX_PROCBASED_CTLS2,
),
@@ -195,7 +197,7 @@ controls = [
name = 'VM-Entry controls',
bits = {
2: 'Load debug controls',
- 9: 'IA-64 mode guest',
+ 9: 'IA-32e mode guest',
10: 'Entry to SMM',
11: 'Deactivate dual-monitor treatment',
13: 'Load IA32_PERF_GLOBAL_CTRL',
@@ -216,7 +218,7 @@ controls = [
8: 'Wait-for-SIPI activity state',
15: 'IA32_SMBASE support',
(16,24): 'Number of CR3-target values',
- (25,27): 'MSR-load/store count recommenation',
+ (25,27): 'MSR-load/store count recommendation',
28: 'IA32_SMM_MONITOR_CTL[2] can be set to 1',
29: 'VMWRITE to VM-exit information fields',
(32,63): 'MSEG revision identifier',
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index b4632324a..d2f815bca 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -177,6 +177,8 @@ const int %(name)s_qtypes[QTYPE_MAX] = {
qtype = "QTYPE_QDICT"
elif find_union(qapi_type):
qtype = "QTYPE_QDICT"
+ elif find_enum(qapi_type):
+ qtype = "QTYPE_QSTRING"
else:
assert False, "Invalid anonymous union member"
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index c12969721..8f845a2b2 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -263,7 +263,8 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
for key in members:
assert (members[key] in builtin_types
or find_struct(members[key])
- or find_union(members[key])), "Invalid anonymous union member"
+ or find_union(members[key])
+ or find_enum(members[key])), "Invalid anonymous union member"
enum_full_value = generate_enum_full_value(disc_type, key)
ret += mcgen('''
@@ -357,6 +358,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
if (err) {
goto out_obj;
}
+ if (!visit_start_union(m, !!(*obj)->data, &err) || err) {
+ goto out_obj;
+ }
switch ((*obj)->kind) {
''',
disc_type = disc_type,
@@ -385,6 +389,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
out_obj:
error_propagate(errp, err);
err = NULL;
+ visit_end_union(m, !!(*obj)->data, &err);
+ error_propagate(errp, err);
+ err = NULL;
}
visit_end_struct(m, &err);
out:
diff --git a/scripts/qapi.py b/scripts/qapi.py
index f2c6d1f84..77d46aa99 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -107,10 +107,10 @@ class QAPISchema:
'Expected a file name (string), got: %s'
% include)
include_path = os.path.join(self.input_dir, include)
- if any(include_path == elem[1]
- for elem in self.include_hist):
- raise QAPIExprError(expr_info, "Inclusion loop for %s"
- % include)
+ for elem in self.include_hist:
+ if include_path == elem[1]:
+ raise QAPIExprError(expr_info, "Inclusion loop for %s"
+ % include)
# skip multiple include of the same file
if include_path in previously_included:
continue
diff --git a/scripts/qtest b/scripts/qtest
deleted file mode 100755
index 4ef6c1c50..000000000
--- a/scripts/qtest
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-export QTEST_QEMU_BINARY=$1
-shift
-"$@"
diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py
index 1aa9460e4..3916c6d14 100755
--- a/scripts/simpletrace.py
+++ b/scripts/simpletrace.py
@@ -58,8 +58,8 @@ def read_record(edict, fobj):
rechdr = read_header(fobj, rec_header_fmt)
return get_record(edict, rechdr, fobj) # return tuple of record elements
-def read_trace_file(edict, fobj):
- """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6)."""
+def read_trace_header(fobj):
+ """Read and verify trace file header"""
header = read_header(fobj, log_header_fmt)
if header is None or \
header[0] != header_event_id or \
@@ -73,6 +73,8 @@ def read_trace_file(edict, fobj):
raise ValueError('Log format %d not supported with this QEMU release!'
% log_version)
+def read_trace_records(edict, fobj):
+ """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6)."""
while True:
rec = read_record(edict, fobj)
if rec is None:
@@ -102,13 +104,16 @@ class Analyzer(object):
"""Called at the end of the trace."""
pass
-def process(events, log, analyzer):
+def process(events, log, analyzer, read_header=True):
"""Invoke an analyzer on each event in a log."""
if isinstance(events, str):
events = _read_events(open(events, 'r'))
if isinstance(log, str):
log = open(log, 'rb')
+ if read_header:
+ read_trace_header(log)
+
dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)")
edict = {dropped_event_id: dropped_event}
@@ -137,7 +142,7 @@ def process(events, log, analyzer):
analyzer.begin()
fn_cache = {}
- for rec in read_trace_file(edict, log):
+ for rec in read_trace_records(edict, log):
event_num = rec[0]
event = edict[event_num]
if event_num not in fn_cache:
@@ -152,12 +157,17 @@ def run(analyzer):
advanced scripts will want to call process() instead."""
import sys
- if len(sys.argv) != 3:
- sys.stderr.write('usage: %s <trace-events> <trace-file>\n' % sys.argv[0])
+ 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] <trace-events> ' \
+ '<trace-file>\n' % sys.argv[0])
sys.exit(1)
events = _read_events(open(sys.argv[1], 'r'))
- process(events, sys.argv[2], analyzer)
+ process(events, sys.argv[2], analyzer, read_header=read_header)
if __name__ == '__main__':
class Formatter(Analyzer):
diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py
index e8e8edcc4..181675f00 100644
--- a/scripts/tracetool/__init__.py
+++ b/scripts/tracetool/__init__.py
@@ -15,9 +15,11 @@ __email__ = "stefanha@linux.vnet.ibm.com"
import re
import sys
+import weakref
import tracetool.format
import tracetool.backend
+import tracetool.transform
def error_write(*lines):
@@ -108,6 +110,18 @@ class Arguments:
"""List of argument types."""
return [ type_ for type_, _ in self._args ]
+ def transform(self, *trans):
+ """Return a new Arguments instance with transformed types.
+
+ The types in the resulting Arguments instance are transformed according
+ to tracetool.transform.transform_type.
+ """
+ res = []
+ for type_, name in self._args:
+ res.append((tracetool.transform.transform_type(type_, *trans),
+ name))
+ return Arguments(res)
+
class Event(object):
"""Event description.
@@ -122,13 +136,19 @@ class Event(object):
Properties of the event.
args : Arguments
The event arguments.
+
"""
- _CRE = re.compile("((?P<props>.*)\s+)?(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?")
+ _CRE = re.compile("((?P<props>[\w\s]+)\s+)?"
+ "(?P<name>\w+)"
+ "\((?P<args>[^)]*)\)"
+ "\s*"
+ "(?:(?:(?P<fmt_trans>\".+),)?\s*(?P<fmt>\".+))?"
+ "\s*")
- _VALID_PROPS = set(["disable"])
+ _VALID_PROPS = set(["disable", "tcg", "tcg-trans", "tcg-exec"])
- def __init__(self, name, props, fmt, args):
+ def __init__(self, name, props, fmt, args, orig=None):
"""
Parameters
----------
@@ -136,20 +156,29 @@ class Event(object):
Event name.
props : list of str
Property names.
- fmt : str
- Event printing format.
+ fmt : str, list of str
+ Event printing format (or formats).
args : Arguments
Event arguments.
+ orig : Event or None
+ Original Event before transformation.
+
"""
self.name = name
self.properties = props
self.fmt = fmt
self.args = args
+ if orig is None:
+ self.original = weakref.ref(self)
+ else:
+ self.original = orig
+
unknown_props = set(self.properties) - self._VALID_PROPS
if len(unknown_props) > 0:
raise ValueError("Unknown properties: %s"
% ", ".join(unknown_props))
+ assert isinstance(self.fmt, str) or len(self.fmt) == 2
def copy(self):
"""Create a new copy."""
@@ -172,34 +201,96 @@ class Event(object):
name = groups["name"]
props = groups["props"].split()
fmt = groups["fmt"]
+ fmt_trans = groups["fmt_trans"]
+ if len(fmt_trans) > 0:
+ fmt = [fmt_trans, fmt]
args = Arguments.build(groups["args"])
+ if "tcg-trans" in props:
+ raise ValueError("Invalid property 'tcg-trans'")
+ if "tcg-exec" in props:
+ raise ValueError("Invalid property 'tcg-exec'")
+ if "tcg" not in props and not isinstance(fmt, str):
+ raise ValueError("Only events with 'tcg' property can have two formats")
+ if "tcg" in props and isinstance(fmt, str):
+ raise ValueError("Events with 'tcg' property must have two formats")
+
return Event(name, props, fmt, args)
def __repr__(self):
"""Evaluable string representation for this object."""
+ if isinstance(self.fmt, str):
+ fmt = self.fmt
+ else:
+ fmt = "%s, %s" % (self.fmt[0], self.fmt[1])
return "Event('%s %s(%s) %s')" % (" ".join(self.properties),
self.name,
self.args,
- self.fmt)
+ fmt)
+
+ _FMT = re.compile("(%[\d\.]*\w+|%.*PRI\S+)")
+
+ def formats(self):
+ """List of argument print formats."""
+ assert not isinstance(self.fmt, list)
+ return self._FMT.findall(self.fmt)
QEMU_TRACE = "trace_%(name)s"
+ QEMU_TRACE_TCG = QEMU_TRACE + "_tcg"
def api(self, fmt=None):
if fmt is None:
fmt = Event.QEMU_TRACE
return fmt % {"name": self.name}
+ def transform(self, *trans):
+ """Return a new Event with transformed Arguments."""
+ return Event(self.name,
+ list(self.properties),
+ self.fmt,
+ self.args.transform(*trans),
+ self)
+
def _read_events(fobj):
- res = []
+ events = []
for line in fobj:
if not line.strip():
continue
if line.lstrip().startswith('#'):
continue
- res.append(Event.build(line))
- return res
+
+ event = Event.build(line)
+
+ # transform TCG-enabled events
+ if "tcg" not in event.properties:
+ events.append(event)
+ else:
+ event_trans = event.copy()
+ event_trans.name += "_trans"
+ event_trans.properties += ["tcg-trans"]
+ event_trans.fmt = event.fmt[0]
+ args_trans = []
+ for atrans, aorig in zip(
+ event_trans.transform(tracetool.transform.TCG_2_HOST).args,
+ event.args):
+ if atrans == aorig:
+ args_trans.append(atrans)
+ event_trans.args = Arguments(args_trans)
+ event_trans = event_trans.copy()
+
+ event_exec = event.copy()
+ event_exec.name += "_exec"
+ event_exec.properties += ["tcg-exec"]
+ event_exec.fmt = event.fmt[1]
+ event_exec = event_exec.transform(tracetool.transform.TCG_2_HOST)
+
+ new_event = [event_trans, event_exec]
+ event.event_trans, event.event_exec = new_event
+
+ events.extend(new_event)
+
+ return events
class TracetoolError (Exception):
diff --git a/scripts/tracetool/backend/__init__.py b/scripts/tracetool/backend/__init__.py
index 5bfa1efc5..d4b6dab9c 100644
--- a/scripts/tracetool/backend/__init__.py
+++ b/scripts/tracetool/backend/__init__.py
@@ -102,7 +102,8 @@ class Wrapper:
def __init__(self, backends, format):
self._backends = [backend.replace("-", "_") for backend in backends]
self._format = format.replace("-", "_")
- assert all(exists(backend) for backend in self._backends)
+ for backend in self._backends:
+ assert exists(backend)
assert tracetool.format.exists(self._format)
def _run_function(self, name, *args, **kwargs):
diff --git a/scripts/tracetool/format/events_h.py b/scripts/tracetool/format/events_h.py
index 25d913bb2..9f114a349 100644
--- a/scripts/tracetool/format/events_h.py
+++ b/scripts/tracetool/format/events_h.py
@@ -40,6 +40,11 @@ def generate(events, backend):
enabled = 0
else:
enabled = 1
+ if "tcg-trans" in e.properties:
+ # a single define for the two "sub-events"
+ out('#define TRACE_%(name)s_ENABLED %(enabled)d',
+ name=e.original.original.name.upper(),
+ enabled=enabled)
out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled))
out('#include "trace/event-internal.h"',
diff --git a/scripts/tracetool/format/simpletrace_stap.py b/scripts/tracetool/format/simpletrace_stap.py
new file mode 100644
index 000000000..7e44bc181
--- /dev/null
+++ b/scripts/tracetool/format/simpletrace_stap.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .stp file that outputs simpletrace binary traces (DTrace with SystemTAP only).
+"""
+
+__author__ = "Stefan Hajnoczi <redhat.com>"
+__copyright__ = "Copyright (C) 2014, Red Hat, Inc."
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@redhat.com"
+
+
+from tracetool import out
+from tracetool.backend.dtrace import binary, probeprefix
+from tracetool.backend.simple import is_string
+from tracetool.format.stap import stap_escape
+
+
+def generate(events, backend):
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '')
+
+ for event_id, e in enumerate(events):
+ if 'disable' in e.properties:
+ continue
+
+ out('probe %(probeprefix)s.simpletrace.%(name)s = %(probeprefix)s.%(name)s ?',
+ '{',
+ probeprefix=probeprefix(),
+ name=e.name)
+
+ # Calculate record size
+ sizes = ['24'] # sizeof(TraceRecord)
+ for type_, name in e.args:
+ name = stap_escape(name)
+ if is_string(type_):
+ out(' try {',
+ ' arg%(name)s_str = %(name)s ? user_string_n(%(name)s, 512) : "<null>"',
+ ' } catch {}',
+ ' arg%(name)s_len = strlen(arg%(name)s_str)',
+ name=name)
+ sizes.append('4 + arg%s_len' % name)
+ else:
+ sizes.append('8')
+ sizestr = ' + '.join(sizes)
+
+ # Generate format string and value pairs for record header and arguments
+ fields = [('8b', str(event_id)),
+ ('8b', 'gettimeofday_ns()'),
+ ('4b', sizestr),
+ ('4b', 'pid()')]
+ for type_, name in e.args:
+ name = stap_escape(name)
+ if is_string(type_):
+ fields.extend([('4b', 'arg%s_len' % name),
+ ('.*s', 'arg%s_len, arg%s_str' % (name, name))])
+ else:
+ fields.append(('8b', name))
+
+ # Emit the entire record in a single SystemTap printf()
+ fmt_str = '%'.join(fmt for fmt, _ in fields)
+ arg_str = ', '.join(arg for _, arg in fields)
+ out(' printf("%%%(fmt_str)s", %(arg_str)s)',
+ fmt_str=fmt_str, arg_str=arg_str)
+
+ out('}')
+
+ out()
diff --git a/scripts/tracetool/format/stap.py b/scripts/tracetool/format/stap.py
index e24abf7f1..9e780f1b0 100644
--- a/scripts/tracetool/format/stap.py
+++ b/scripts/tracetool/format/stap.py
@@ -27,6 +27,13 @@ RESERVED_WORDS = (
)
+def stap_escape(identifier):
+ # Append underscore to reserved keywords
+ if identifier in RESERVED_WORDS:
+ return identifier + '_'
+ return identifier
+
+
def generate(events, backend):
events = [e for e in events
if "disable" not in e.properties]
@@ -45,9 +52,7 @@ def generate(events, backend):
i = 1
if len(e.args) > 0:
for name in e.args.names():
- # Append underscore to reserved keywords
- if name in RESERVED_WORDS:
- name += '_'
+ name = stap_escape(name)
out(' %s = $arg%d;' % (name, i))
i += 1
diff --git a/scripts/tracetool/format/tcg_h.py b/scripts/tracetool/format/tcg_h.py
new file mode 100644
index 000000000..f676b6662
--- /dev/null
+++ b/scripts/tracetool/format/tcg_h.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .h file for TCG code generation.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@linux.vnet.ibm.com"
+
+
+from tracetool import out
+
+
+def generate(events, backend):
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '/* You must include this file after the inclusion of helper.h */',
+ '',
+ '#ifndef TRACE__GENERATED_TCG_TRACERS_H',
+ '#define TRACE__GENERATED_TCG_TRACERS_H',
+ '',
+ '#include <stdint.h>',
+ '',
+ '#include "trace.h"',
+ '#include "exec/helper-proto.h"',
+ '',
+ )
+
+ for e in events:
+ # just keep one of them
+ if "tcg-trans" not in e.properties:
+ continue
+
+ # get the original event definition
+ e = e.original.original
+
+ out('static inline void %(name_tcg)s(%(args)s)',
+ '{',
+ name_tcg=e.api(e.QEMU_TRACE_TCG),
+ args=e.args)
+
+ if "disable" not in e.properties:
+ out(' %(name_trans)s(%(argnames_trans)s);',
+ ' gen_helper_%(name_exec)s(%(argnames_exec)s);',
+ name_trans=e.event_trans.api(e.QEMU_TRACE),
+ name_exec=e.event_exec.api(e.QEMU_TRACE),
+ argnames_trans=", ".join(e.event_trans.args.names()),
+ argnames_exec=", ".join(e.event_exec.args.names()))
+
+ out('}')
+
+ out('',
+ '#endif /* TRACE__GENERATED_TCG_TRACERS_H */')
diff --git a/scripts/tracetool/format/tcg_helper_c.py b/scripts/tracetool/format/tcg_helper_c.py
new file mode 100644
index 000000000..96655a059
--- /dev/null
+++ b/scripts/tracetool/format/tcg_helper_c.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate trace/generated-helpers.c.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@linux.vnet.ibm.com"
+
+
+from tracetool import out
+from tracetool.transform import *
+
+
+def generate(events, backend):
+ events = [e for e in events
+ if "disable" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#include "qemu-common.h"',
+ '#include "trace.h"',
+ '#include "exec/helper-proto.h"',
+ '',
+ )
+
+ for e in events:
+ if "tcg-exec" not in e.properties:
+ continue
+
+ # tracetool.generate always transforms types to host
+ e_args = e.original.args
+
+ values = ["(%s)%s" % (t, n)
+ for t, n in e.args.transform(TCG_2_TCG_HELPER_DEF)]
+
+ out('void %(name_tcg)s(%(args)s)',
+ '{',
+ ' %(name)s(%(values)s);',
+ '}',
+ name_tcg="helper_%s_proxy" % e.api(),
+ name=e.api(),
+ args=e_args.transform(HOST_2_TCG_COMPAT, TCG_2_TCG_HELPER_DEF),
+ values=", ".join(values),
+ )
diff --git a/scripts/tracetool/format/tcg_helper_h.py b/scripts/tracetool/format/tcg_helper_h.py
new file mode 100644
index 000000000..a8ba7ba8e
--- /dev/null
+++ b/scripts/tracetool/format/tcg_helper_h.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate trace/generated-helpers.h.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@linux.vnet.ibm.com"
+
+
+from tracetool import out
+from tracetool.transform import *
+
+
+def generate(events, backend):
+ events = [e for e in events
+ if "disable" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ )
+
+ for e in events:
+ if "tcg-exec" not in e.properties:
+ continue
+
+ # tracetool.generate always transforms types to host
+ e_args = e.original.args
+
+ # TCG helper proxy declaration
+ fmt = "DEF_HELPER_FLAGS_%(argc)d(%(name)s, %(flags)svoid%(types)s)"
+ args = e_args.transform(HOST_2_TCG_COMPAT, HOST_2_TCG,
+ TCG_2_TCG_HELPER_DECL)
+ types = ", ".join(args.types())
+ if types != "":
+ types = ", " + types
+
+ flags = "TCG_CALL_NO_RWG, "
+
+ out(fmt,
+ flags=flags,
+ argc=len(args),
+ name=e.api() + "_proxy",
+ types=types,
+ )
diff --git a/scripts/tracetool/format/tcg_helper_wrapper_h.py b/scripts/tracetool/format/tcg_helper_wrapper_h.py
new file mode 100644
index 000000000..cac5a878f
--- /dev/null
+++ b/scripts/tracetool/format/tcg_helper_wrapper_h.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate trace/generated-helpers-wrappers.h.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@linux.vnet.ibm.com"
+
+
+from tracetool import out
+from tracetool.transform import *
+
+
+def generate(events, backend):
+ events = [e for e in events
+ if "disable" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#define tcg_temp_new_nop(v) (v)',
+ '#define tcg_temp_free_nop(v)',
+ '',
+ )
+
+ for e in events:
+ if "tcg-exec" not in e.properties:
+ continue
+
+ # tracetool.generate always transforms types to host
+ e_args = e.original.args
+
+ # mixed-type to TCG helper bridge
+ args_tcg_compat = e_args.transform(HOST_2_TCG_COMPAT)
+
+ code_new = [
+ "%(tcg_type)s __%(name)s = %(tcg_func)s(%(name)s);" %
+ {"tcg_type": transform_type(type_, HOST_2_TCG),
+ "tcg_func": transform_type(type_, HOST_2_TCG_TMP_NEW),
+ "name": name}
+ for (type_, name) in args_tcg_compat
+ ]
+
+ code_free = [
+ "%(tcg_func)s(__%(name)s);" %
+ {"tcg_func": transform_type(type_, HOST_2_TCG_TMP_FREE),
+ "name": name}
+ for (type_, name) in args_tcg_compat
+ ]
+
+ gen_name = "gen_helper_" + e.api()
+
+ out('static inline void %(name)s(%(args)s)',
+ '{',
+ ' %(code_new)s',
+ ' %(proxy_name)s(%(tmp_names)s);',
+ ' %(code_free)s',
+ '}',
+ name=gen_name,
+ args=e_args,
+ proxy_name=gen_name + "_proxy",
+ code_new="\n ".join(code_new),
+ code_free="\n ".join(code_free),
+ tmp_names=", ".join(["__%s" % name for _, name in e_args]),
+ )
diff --git a/scripts/tracetool/format/ust_events_h.py b/scripts/tracetool/format/ust_events_h.py
index 510256547..3e8a7cdf1 100644
--- a/scripts/tracetool/format/ust_events_h.py
+++ b/scripts/tracetool/format/ust_events_h.py
@@ -63,13 +63,20 @@ def generate(events, backend):
name=e.name,
args=", ".join(", ".join(i) for i in e.args))
- for t, n in e.args:
- if ('int' in t) or ('long' in t) or ('unsigned' in t) or ('size_t' in t):
+ types = e.args.types()
+ names = e.args.names()
+ fmts = e.formats()
+ for t,n,f in zip(types, names, fmts):
+ if ('char *' in t) or ('char*' in t):
+ out(' ctf_string(' + n + ', ' + n + ')')
+ elif ("%p" in f) or ("x" in f) or ("PRIx" in f):
+ out(' ctf_integer_hex('+ t + ', ' + n + ', ' + n + ')')
+ elif ("ptr" in t) or ("*" in t):
+ out(' ctf_integer_hex('+ t + ', ' + n + ', ' + n + ')')
+ elif ('int' in t) or ('long' in t) or ('unsigned' in t) or ('size_t' in t):
out(' ctf_integer(' + t + ', ' + n + ', ' + n + ')')
elif ('double' in t) or ('float' in t):
out(' ctf_float(' + t + ', ' + n + ', ' + n + ')')
- elif ('char *' in t) or ('char*' in t):
- out(' ctf_string(' + n + ', ' + n + ')')
elif ('void *' in t) or ('void*' in t):
out(' ctf_integer_hex(unsigned long, ' + n + ', ' + n + ')')
diff --git a/scripts/tracetool/transform.py b/scripts/tracetool/transform.py
new file mode 100644
index 000000000..fc5e679ed
--- /dev/null
+++ b/scripts/tracetool/transform.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Type-transformation rules.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@linux.vnet.ibm.com"
+
+
+def _transform_type(type_, trans):
+ if isinstance(trans, str):
+ return trans
+ elif isinstance(trans, dict):
+ if type_ in trans:
+ return _transform_type(type_, trans[type_])
+ elif None in trans:
+ return _transform_type(type_, trans[None])
+ else:
+ return type_
+ elif callable(trans):
+ return trans(type_)
+ else:
+ raise ValueError("Invalid type transformation rule: %s" % trans)
+
+
+def transform_type(type_, *trans):
+ """Return a new type transformed according to the given rules.
+
+ Applies each of the transformation rules in trans in order.
+
+ If an element of trans is a string, return it.
+
+ If an element of trans is a function, call it with type_ as its only
+ argument.
+
+ If an element of trans is a dict, search type_ in its keys. If type_ is
+ a key, use the value as a transformation rule for type_. Otherwise, if
+ None is a key use the value as a transformation rule for type_.
+
+ Otherwise, return type_.
+
+ Parameters
+ ----------
+ type_ : str
+ Type to transform.
+ trans : list of function or dict
+ Type transformation rules.
+ """
+ if len(trans) == 0:
+ raise ValueError
+ res = type_
+ for t in trans:
+ res = _transform_type(res, t)
+ return res
+
+
+##################################################
+# tcg -> host
+
+def _tcg_2_host(type_):
+ if type_ == "TCGv":
+ # force a fixed-size type (target-independent)
+ return "uint64_t"
+ else:
+ return type_
+
+TCG_2_HOST = {
+ "TCGv_i32": "uint32_t",
+ "TCGv_i64": "uint64_t",
+ "TCGv_ptr": "void *",
+ None: _tcg_2_host,
+ }
+
+
+##################################################
+# host -> host compatible with tcg sizes
+
+HOST_2_TCG_COMPAT = {
+ "uint8_t": "uint32_t",
+ }
+
+
+##################################################
+# host/tcg -> tcg
+
+def _host_2_tcg(type_):
+ if type_.startswith("TCGv"):
+ return type_
+ raise ValueError("Don't know how to translate '%s' into a TCG type\n" % type_)
+
+HOST_2_TCG = {
+ "uint32_t": "TCGv_i32",
+ "uint64_t": "TCGv_i64",
+ "void *" : "TCGv_ptr",
+ None: _host_2_tcg,
+ }
+
+
+##################################################
+# tcg -> tcg helper definition
+
+def _tcg_2_helper_def(type_):
+ if type_ == "TCGv":
+ return "target_ulong"
+ else:
+ return type_
+
+TCG_2_TCG_HELPER_DEF = {
+ "TCGv_i32": "uint32_t",
+ "TCGv_i64": "uint64_t",
+ "TCGv_ptr": "void *",
+ None: _tcg_2_helper_def,
+ }
+
+
+##################################################
+# tcg -> tcg helper declaration
+
+def _tcg_2_tcg_helper_decl_error(type_):
+ raise ValueError("Don't know how to translate type '%s' into a TCG helper declaration type\n" % type_)
+
+TCG_2_TCG_HELPER_DECL = {
+ "TCGv" : "tl",
+ "TCGv_ptr": "ptr",
+ "TCGv_i32": "i32",
+ "TCGv_i64": "i64",
+ None: _tcg_2_tcg_helper_decl_error,
+ }
+
+
+##################################################
+# host/tcg -> tcg temporal constant allocation
+
+def _host_2_tcg_tmp_new(type_):
+ if type_.startswith("TCGv"):
+ return "tcg_temp_new_nop"
+ raise ValueError("Don't know how to translate type '%s' into a TCG temporal allocation" % type_)
+
+HOST_2_TCG_TMP_NEW = {
+ "uint32_t": "tcg_const_i32",
+ "uint64_t": "tcg_const_i64",
+ "void *" : "tcg_const_ptr",
+ None: _host_2_tcg_tmp_new,
+ }
+
+
+##################################################
+# host/tcg -> tcg temporal constant deallocation
+
+def _host_2_tcg_tmp_free(type_):
+ if type_.startswith("TCGv"):
+ return "tcg_temp_free_nop"
+ raise ValueError("Don't know how to translate type '%s' into a TCG temporal deallocation" % type_)
+
+HOST_2_TCG_TMP_FREE = {
+ "uint32_t": "tcg_temp_free_i32",
+ "uint64_t": "tcg_temp_free_i64",
+ "void *" : "tcg_temp_free_ptr",
+ None: _host_2_tcg_tmp_free,
+ }
diff --git a/scripts/vmstate-static-checker.py b/scripts/vmstate-static-checker.py
index 3bae769a3..f7ce3fc48 100755
--- a/scripts/vmstate-static-checker.py
+++ b/scripts/vmstate-static-checker.py
@@ -42,30 +42,44 @@ def check_fields_match(name, s_field, d_field):
# Some fields changed names between qemu versions. This list
# is used to whitelist such changes in each section / description.
changed_names = {
+ 'apic': ['timer', 'timer_expiry'],
'e1000': ['dev', 'parent_obj'],
'ehci': ['dev', 'pcidev'],
'I440FX': ['dev', 'parent_obj'],
'ich9_ahci': ['card', 'parent_obj'],
+ 'ich9-ahci': ['ahci', 'ich9_ahci'],
+ 'ioh3420': ['PCIDevice', 'PCIEDevice'],
'ioh-3240-express-root-port': ['port.br.dev',
'parent_obj.parent_obj.parent_obj',
'port.br.dev.exp.aer_log',
'parent_obj.parent_obj.parent_obj.exp.aer_log'],
+ 'lsiscsi': ['dev', 'parent_obj'],
'mch': ['d', 'parent_obj'],
'pci_bridge': ['bridge.dev', 'parent_obj', 'bridge.dev.shpc', 'shpc'],
'pcnet': ['pci_dev', 'parent_obj'],
'PIIX3': ['pci_irq_levels', 'pci_irq_levels_vmstate'],
'piix4_pm': ['dev', 'parent_obj', 'pci0_status',
- 'acpi_pci_hotplug.acpi_pcihp_pci_status[0x0]'],
+ 'acpi_pci_hotplug.acpi_pcihp_pci_status[0x0]',
+ 'pm1a.sts', 'ar.pm1.evt.sts', 'pm1a.en', 'ar.pm1.evt.en',
+ 'pm1_cnt.cnt', 'ar.pm1.cnt.cnt',
+ 'tmr.timer', 'ar.tmr.timer',
+ 'tmr.overflow_time', 'ar.tmr.overflow_time',
+ 'gpe', 'ar.gpe'],
'rtl8139': ['dev', 'parent_obj'],
'qxl': ['num_surfaces', 'ssd.num_surfaces'],
+ 'usb-ccid': ['abProtocolDataStructure', 'abProtocolDataStructure.data'],
'usb-host': ['dev', 'parent_obj'],
'usb-mouse': ['usb-ptr-queue', 'HIDPointerEventQueue'],
'usb-tablet': ['usb-ptr-queue', 'HIDPointerEventQueue'],
+ 'vmware_vga': ['card', 'parent_obj'],
+ 'vmware_vga_internal': ['depth', 'new_depth'],
'xhci': ['pci_dev', 'parent_obj'],
+ 'x3130-upstream': ['PCIDevice', 'PCIEDevice'],
'xio3130-express-downstream-port': ['port.br.dev',
'parent_obj.parent_obj.parent_obj',
'port.br.dev.exp.aer_log',
'parent_obj.parent_obj.parent_obj.exp.aer_log'],
+ 'xio3130-downstream': ['PCIDevice', 'PCIEDevice'],
'xio3130-express-upstream-port': ['br.dev', 'parent_obj.parent_obj',
'br.dev.exp.aer_log',
'parent_obj.parent_obj.exp.aer_log'],
@@ -130,6 +144,7 @@ def check_fields(src_fields, dest_fields, desc, sec):
advance_src = True
advance_dest = True
+ unused_count = 0
while True:
if advance_src:
@@ -142,9 +157,10 @@ def check_fields(src_fields, dest_fields, desc, sec):
s_iter = s_iter_list.pop()
continue
else:
- # We want to avoid advancing just once -- when entering a
- # dest substruct, or when exiting one.
- advance_src = True
+ if unused_count == 0:
+ # We want to avoid advancing just once -- when entering a
+ # dest substruct, or when exiting one.
+ advance_src = True
if advance_dest:
try:
@@ -163,7 +179,37 @@ def check_fields(src_fields, dest_fields, desc, sec):
advance_src = False
continue
else:
- advance_dest = True
+ if unused_count == 0:
+ advance_dest = True
+
+ if unused_count > 0:
+ if advance_dest == False:
+ unused_count = unused_count - s_item["size"]
+ if unused_count == 0:
+ advance_dest = True
+ continue
+ if unused_count < 0:
+ print "Section \"" + sec + "\",",
+ print "Description \"" + desc + "\":",
+ print "unused size mismatch near \"",
+ print s_item["field"] + "\""
+ bump_taint()
+ break
+ continue
+
+ if advance_src == False:
+ unused_count = unused_count - d_item["size"]
+ if unused_count == 0:
+ advance_src = True
+ continue
+ if unused_count < 0:
+ print "Section \"" + sec + "\",",
+ print "Description \"" + desc + "\":",
+ print "unused size mismatch near \"",
+ print d_item["field"] + "\""
+ bump_taint()
+ break
+ continue
if not check_fields_match(desc, s_item["field"], d_item["field"]):
# Some fields were put in substructs, keeping the
@@ -194,6 +240,20 @@ def check_fields(src_fields, dest_fields, desc, sec):
advance_dest = False
continue
+ if s_item["field"] == "unused" or d_item["field"] == "unused":
+ if s_item["size"] == d_item["size"]:
+ continue
+
+ if d_item["field"] == "unused":
+ advance_dest = False
+ unused_count = d_item["size"] - s_item["size"]
+ continue
+
+ if s_item["field"] == "unused":
+ advance_src = False
+ unused_count = s_item["size"] - d_item["size"]
+ continue
+
print "Section \"" + sec + "\",",
print "Description \"" + desc + "\":",
print "expected field \"" + s_item["field"] + "\",",