aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/coccinelle
diff options
context:
space:
mode:
authorTimos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>2023-10-10 11:40:56 +0000
committerTimos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>2023-10-10 11:40:56 +0000
commite02cda008591317b1625707ff8e115a4841aa889 (patch)
treeaee302e3cf8b59ec2d32ec481be3d1afddfc8968 /scripts/coccinelle
parentcc668e6b7e0ffd8c9d130513d12053cf5eda1d3b (diff)
Introduce Virtio-loopback epsilon release:
Epsilon release introduces a new compatibility layer which make virtio-loopback design to work with QEMU and rust-vmm vhost-user backend without require any changes. Signed-off-by: Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com> Change-Id: I52e57563e08a7d0bdc002f8e928ee61ba0c53dd9
Diffstat (limited to 'scripts/coccinelle')
-rw-r--r--scripts/coccinelle/cpu-reset.cocci47
-rw-r--r--scripts/coccinelle/cpu_restore_state.cocci19
-rw-r--r--scripts/coccinelle/err-bad-newline.cocci49
-rw-r--r--scripts/coccinelle/error-use-after-free.cocci52
-rw-r--r--scripts/coccinelle/error_propagate_null.cocci10
-rw-r--r--scripts/coccinelle/errp-guard.cocci336
-rw-r--r--scripts/coccinelle/exec_rw_const.cocci111
-rw-r--r--scripts/coccinelle/inplace-byteswaps.cocci65
-rw-r--r--scripts/coccinelle/memory-region-housekeeping.cocci159
-rw-r--r--scripts/coccinelle/overflow_muldiv64.cocci16
-rw-r--r--scripts/coccinelle/qobject.cocci47
-rw-r--r--scripts/coccinelle/qom-parent-type.cocci26
-rw-r--r--scripts/coccinelle/remove_local_err.cocci29
-rw-r--r--scripts/coccinelle/remove_muldiv64.cocci6
-rw-r--r--scripts/coccinelle/return_directly.cocci19
-rw-r--r--scripts/coccinelle/round.cocci19
-rw-r--r--scripts/coccinelle/simplify_muldiv64.cocci11
-rw-r--r--scripts/coccinelle/swap_muldiv64.cocci13
-rw-r--r--scripts/coccinelle/tcg_gen_extract.cocci107
-rw-r--r--scripts/coccinelle/timer-del-timer-free.cocci18
-rw-r--r--scripts/coccinelle/typecast.cocci7
-rw-r--r--scripts/coccinelle/use-error_fatal.cocci20
22 files changed, 1186 insertions, 0 deletions
diff --git a/scripts/coccinelle/cpu-reset.cocci b/scripts/coccinelle/cpu-reset.cocci
new file mode 100644
index 000000000..396a724e5
--- /dev/null
+++ b/scripts/coccinelle/cpu-reset.cocci
@@ -0,0 +1,47 @@
+// Convert targets using the old CPUState reset to DeviceState reset
+//
+// Copyright Linaro Ltd 2020
+// This work is licensed under the terms of the GNU GPLv2 or later.
+//
+// spatch --macro-file scripts/cocci-macro-file.h \
+// --sp-file scripts/coccinelle/cpu-reset.cocci \
+// --keep-comments --smpl-spacing --in-place --include-headers --dir target
+//
+// For simplicity we assume some things about the code we're modifying
+// that happen to be true for all our targets:
+// * all cpu_class_set_parent_reset() callsites have a 'DeviceClass *dc' local
+// * the parent reset field in the target CPU class is 'parent_reset'
+// * no reset function already has a 'dev' local
+
+@@
+identifier cpu, x;
+typedef CPUState;
+@@
+struct x {
+...
+- void (*parent_reset)(CPUState *cpu);
++ DeviceReset parent_reset;
+...
+};
+@ rule1 @
+identifier resetfn;
+expression resetfield;
+identifier cc;
+@@
+- cpu_class_set_parent_reset(cc, resetfn, resetfield)
++ device_class_set_parent_reset(dc, resetfn, resetfield)
+@@
+identifier rule1.resetfn;
+identifier cpu, cc;
+typedef CPUState, DeviceState;
+@@
+-resetfn(CPUState *cpu)
+-{
++resetfn(DeviceState *dev)
++{
++ CPUState *cpu = CPU(dev);
+<...
+- cc->parent_reset(cpu);
++ cc->parent_reset(dev);
+...>
+}
diff --git a/scripts/coccinelle/cpu_restore_state.cocci b/scripts/coccinelle/cpu_restore_state.cocci
new file mode 100644
index 000000000..61bc749d1
--- /dev/null
+++ b/scripts/coccinelle/cpu_restore_state.cocci
@@ -0,0 +1,19 @@
+// Remove unneeded tests before calling cpu_restore_state
+//
+// spatch --macro-file scripts/cocci-macro-file.h \
+// --sp-file ./scripts/coccinelle/cpu_restore_state.cocci \
+// --keep-comments --in-place --use-gitgrep --dir target
+@@
+expression A;
+expression C;
+@@
+-if (A) {
+ cpu_restore_state(C, A);
+-}
+@@
+expression A;
+expression C;
+@@
+- cpu_restore_state(C, A);
+- cpu_loop_exit(C);
++ cpu_loop_exit_restore(C, A);
diff --git a/scripts/coccinelle/err-bad-newline.cocci b/scripts/coccinelle/err-bad-newline.cocci
new file mode 100644
index 000000000..539442187
--- /dev/null
+++ b/scripts/coccinelle/err-bad-newline.cocci
@@ -0,0 +1,49 @@
+// Error messages should not contain newlines. This script finds
+// messages that do. Fixing them is manual.
+@r@
+expression errp, err, eno, cls, fmt, ap;
+position p;
+@@
+(
+error_vreport(fmt, ap)@p
+|
+warn_vreport(fmt, ap)@p
+|
+info_vreport(fmt, ap)@p
+|
+error_report(fmt, ...)@p
+|
+warn_report(fmt, ...)@p
+|
+info_report(fmt, ...)@p
+|
+error_report_once(fmt, ...)@p
+|
+warn_report_once(fmt, ...)@p
+|
+error_setg(errp, fmt, ...)@p
+|
+error_setg_errno(errp, eno, fmt, ...)@p
+|
+error_setg_win32(errp, eno, cls, fmt, ...)@p
+|
+error_propagate_prepend(errp, err, fmt, ...)@p
+|
+error_vprepend(errp, fmt, ap)@p
+|
+error_prepend(errp, fmt, ...)@p
+|
+error_setg_file_open(errp, eno, cls, fmt, ...)@p
+|
+warn_reportf_err(errp, fmt, ...)@p
+|
+error_reportf_err(errp, fmt, ...)@p
+|
+error_set(errp, cls, fmt, ...)@p
+)
+@script:python@
+fmt << r.fmt;
+p << r.p;
+@@
+if "\\n" in str(fmt):
+ print("%s:%s:%s:%s" % (p[0].file, p[0].line, p[0].column, fmt))
diff --git a/scripts/coccinelle/error-use-after-free.cocci b/scripts/coccinelle/error-use-after-free.cocci
new file mode 100644
index 000000000..72ae9fdeb
--- /dev/null
+++ b/scripts/coccinelle/error-use-after-free.cocci
@@ -0,0 +1,52 @@
+// Find and fix trivial use-after-free of Error objects
+//
+// Copyright (c) 2020 Virtuozzo International GmbH.
+//
+// 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
+// <http://www.gnu.org/licenses/>.
+//
+// How to use:
+// spatch --sp-file scripts/coccinelle/error-use-after-free.cocci \
+// --macro-file scripts/cocci-macro-file.h --in-place \
+// --no-show-diff ( FILES... | --use-gitgrep . )
+
+@ exists@
+identifier fn, fn2;
+expression err;
+@@
+
+ fn(...)
+ {
+ <...
+(
+ error_free(err);
++ err = NULL;
+|
+ error_report_err(err);
++ err = NULL;
+|
+ error_reportf_err(err, ...);
++ err = NULL;
+|
+ warn_report_err(err);
++ err = NULL;
+|
+ warn_reportf_err(err, ...);
++ err = NULL;
+)
+ ... when != err = NULL
+ when != exit(...)
+ fn2(..., err, ...)
+ ...>
+ }
diff --git a/scripts/coccinelle/error_propagate_null.cocci b/scripts/coccinelle/error_propagate_null.cocci
new file mode 100644
index 000000000..c23638007
--- /dev/null
+++ b/scripts/coccinelle/error_propagate_null.cocci
@@ -0,0 +1,10 @@
+// error_propagate() already ignores local_err==NULL, so there's
+// no need to check it before calling.
+
+@@
+identifier L;
+expression E;
+@@
+-if (L) {
+ error_propagate(E, L);
+-}
diff --git a/scripts/coccinelle/errp-guard.cocci b/scripts/coccinelle/errp-guard.cocci
new file mode 100644
index 000000000..6e789acf2
--- /dev/null
+++ b/scripts/coccinelle/errp-guard.cocci
@@ -0,0 +1,336 @@
+// Use ERRP_GUARD() (see include/qapi/error.h)
+//
+// Copyright (c) 2020 Virtuozzo International GmbH.
+//
+// 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
+// <http://www.gnu.org/licenses/>.
+//
+// Usage example:
+// spatch --sp-file scripts/coccinelle/errp-guard.cocci \
+// --macro-file scripts/cocci-macro-file.h --in-place \
+// --no-show-diff --max-width 80 FILES...
+//
+// Note: --max-width 80 is needed because coccinelle default is less
+// than 80, and without this parameter coccinelle may reindent some
+// lines which fit into 80 characters but not to coccinelle default,
+// which in turn produces extra patch hunks for no reason.
+
+// Switch unusual Error ** parameter names to errp
+// (this is necessary to use ERRP_GUARD).
+//
+// Disable optional_qualifier to skip functions with
+// "Error *const *errp" parameter.
+//
+// Skip functions with "assert(_errp && *_errp)" statement, because
+// that signals unusual semantics, and the parameter name may well
+// serve a purpose. (like nbd_iter_channel_error()).
+//
+// Skip util/error.c to not touch, for example, error_propagate() and
+// error_propagate_prepend().
+@ depends on !(file in "util/error.c") disable optional_qualifier@
+identifier fn;
+identifier _errp != errp;
+@@
+
+ fn(...,
+- Error **_errp
++ Error **errp
+ ,...)
+ {
+(
+ ... when != assert(_errp && *_errp)
+&
+ <...
+- _errp
++ errp
+ ...>
+)
+ }
+
+// Add invocation of ERRP_GUARD() to errp-functions where // necessary
+//
+// Note, that without "when any" the final "..." does not mach
+// something matched by previous pattern, i.e. the rule will not match
+// double error_prepend in control flow like in
+// vfio_set_irq_signaling().
+//
+// Note, "exists" says that we want apply rule even if it does not
+// match on all possible control flows (otherwise, it will not match
+// standard pattern when error_propagate() call is in if branch).
+@ disable optional_qualifier exists@
+identifier fn, local_err;
+symbol errp;
+@@
+
+ fn(..., Error **errp, ...)
+ {
++ ERRP_GUARD();
+ ... when != ERRP_GUARD();
+(
+(
+ error_append_hint(errp, ...);
+|
+ error_prepend(errp, ...);
+|
+ error_vprepend(errp, ...);
+)
+ ... when any
+|
+ Error *local_err = NULL;
+ ...
+(
+ error_propagate_prepend(errp, local_err, ...);
+|
+ error_propagate(errp, local_err);
+)
+ ...
+)
+ }
+
+// Warn when several Error * definitions are in the control flow.
+// This rule is not chained to rule1 and less restrictive, to cover more
+// functions to warn (even those we are not going to convert).
+//
+// Note, that even with one (or zero) Error * definition in the each
+// control flow we may have several (in total) Error * definitions in
+// the function. This case deserves attention too, but I don't see
+// simple way to match with help of coccinelle.
+@check1 disable optional_qualifier exists@
+identifier fn, _errp, local_err, local_err2;
+position p1, p2;
+@@
+
+ fn(..., Error **_errp, ...)
+ {
+ ...
+ Error *local_err = NULL;@p1
+ ... when any
+ Error *local_err2 = NULL;@p2
+ ... when any
+ }
+
+@ script:python @
+fn << check1.fn;
+p1 << check1.p1;
+p2 << check1.p2;
+@@
+
+print('Warning: function {} has several definitions of '
+ 'Error * local variable: at {}:{} and then at {}:{}'.format(
+ fn, p1[0].file, p1[0].line, p2[0].file, p2[0].line))
+
+// Warn when several propagations are in the control flow.
+@check2 disable optional_qualifier exists@
+identifier fn, _errp;
+position p1, p2;
+@@
+
+ fn(..., Error **_errp, ...)
+ {
+ ...
+(
+ error_propagate_prepend(_errp, ...);@p1
+|
+ error_propagate(_errp, ...);@p1
+)
+ ...
+(
+ error_propagate_prepend(_errp, ...);@p2
+|
+ error_propagate(_errp, ...);@p2
+)
+ ... when any
+ }
+
+@ script:python @
+fn << check2.fn;
+p1 << check2.p1;
+p2 << check2.p2;
+@@
+
+print('Warning: function {} propagates to errp several times in '
+ 'one control flow: at {}:{} and then at {}:{}'.format(
+ fn, p1[0].file, p1[0].line, p2[0].file, p2[0].line))
+
+// Match functions with propagation of local error to errp.
+// We want to refer these functions in several following rules, but I
+// don't know a proper way to inherit a function, not just its name
+// (to not match another functions with same name in following rules).
+// Not-proper way is as follows: rename errp parameter in functions
+// header and match it in following rules. Rename it back after all
+// transformations.
+//
+// The common case is a single definition of local_err with at most one
+// error_propagate_prepend() or error_propagate() on each control-flow
+// path. Functions with multiple definitions or propagates we want to
+// examine manually. Rules check1 and check2 emit warnings to guide us
+// to them.
+//
+// Note that we match not only this "common case", but any function,
+// which has the "common case" on at least one control-flow path.
+@rule1 disable optional_qualifier exists@
+identifier fn, local_err;
+symbol errp;
+@@
+
+ fn(..., Error **
+- errp
++ ____
+ , ...)
+ {
+ ...
+ Error *local_err = NULL;
+ ...
+(
+ error_propagate_prepend(errp, local_err, ...);
+|
+ error_propagate(errp, local_err);
+)
+ ...
+ }
+
+// Convert special case with goto separately.
+// I tried merging this into the following rule the obvious way, but
+// it made Coccinelle hang on block.c
+//
+// Note interesting thing: if we don't do it here, and try to fixup
+// "out: }" things later after all transformations (the rule will be
+// the same, just without error_propagate() call), coccinelle fails to
+// match this "out: }".
+@ disable optional_qualifier@
+identifier rule1.fn, rule1.local_err, out;
+symbol errp;
+@@
+
+ fn(..., Error ** ____, ...)
+ {
+ <...
+- goto out;
++ return;
+ ...>
+- out:
+- error_propagate(errp, local_err);
+ }
+
+// Convert most of local_err related stuff.
+//
+// Note, that we inherit rule1.fn and rule1.local_err names, not
+// objects themselves. We may match something not related to the
+// pattern matched by rule1. For example, local_err may be defined with
+// the same name in different blocks inside one function, and in one
+// block follow the propagation pattern and in other block doesn't.
+//
+// Note also that errp-cleaning functions
+// error_free_errp
+// error_report_errp
+// error_reportf_errp
+// warn_report_errp
+// warn_reportf_errp
+// are not yet implemented. They must call corresponding Error* -
+// freeing function and then set *errp to NULL, to avoid further
+// propagation to original errp (consider ERRP_GUARD in use).
+// For example, error_free_errp may look like this:
+//
+// void error_free_errp(Error **errp)
+// {
+// error_free(*errp);
+// *errp = NULL;
+// }
+@ disable optional_qualifier exists@
+identifier rule1.fn, rule1.local_err;
+expression list args;
+symbol errp;
+@@
+
+ fn(..., Error ** ____, ...)
+ {
+ <...
+(
+- Error *local_err = NULL;
+|
+
+// Convert error clearing functions
+(
+- error_free(local_err);
++ error_free_errp(errp);
+|
+- error_report_err(local_err);
++ error_report_errp(errp);
+|
+- error_reportf_err(local_err, args);
++ error_reportf_errp(errp, args);
+|
+- warn_report_err(local_err);
++ warn_report_errp(errp);
+|
+- warn_reportf_err(local_err, args);
++ warn_reportf_errp(errp, args);
+)
+?- local_err = NULL;
+
+|
+- error_propagate_prepend(errp, local_err, args);
++ error_prepend(errp, args);
+|
+- error_propagate(errp, local_err);
+|
+- &local_err
++ errp
+)
+ ...>
+ }
+
+// Convert remaining local_err usage. For example, different kinds of
+// error checking in if conditionals. We can't merge this into
+// previous hunk, as this conflicts with other substitutions in it (at
+// least with "- local_err = NULL").
+@ disable optional_qualifier@
+identifier rule1.fn, rule1.local_err;
+symbol errp;
+@@
+
+ fn(..., Error ** ____, ...)
+ {
+ <...
+- local_err
++ *errp
+ ...>
+ }
+
+// Always use the same pattern for checking error
+@ disable optional_qualifier@
+identifier rule1.fn;
+symbol errp;
+@@
+
+ fn(..., Error ** ____, ...)
+ {
+ <...
+- *errp != NULL
++ *errp
+ ...>
+ }
+
+// Revert temporary ___ identifier.
+@ disable optional_qualifier@
+identifier rule1.fn;
+@@
+
+ fn(..., Error **
+- ____
++ errp
+ , ...)
+ {
+ ...
+ }
diff --git a/scripts/coccinelle/exec_rw_const.cocci b/scripts/coccinelle/exec_rw_const.cocci
new file mode 100644
index 000000000..1a2029695
--- /dev/null
+++ b/scripts/coccinelle/exec_rw_const.cocci
@@ -0,0 +1,111 @@
+/*
+ Usage:
+
+ spatch \
+ --macro-file scripts/cocci-macro-file.h \
+ --sp-file scripts/coccinelle/exec_rw_const.cocci \
+ --keep-comments \
+ --in-place \
+ --dir .
+*/
+
+// Convert to boolean
+@@
+expression E1, E2, E3, E4, E5;
+@@
+(
+- address_space_rw(E1, E2, E3, E4, E5, 0)
++ address_space_rw(E1, E2, E3, E4, E5, false)
+|
+- address_space_rw(E1, E2, E3, E4, E5, 1)
++ address_space_rw(E1, E2, E3, E4, E5, true)
+|
+
+- cpu_physical_memory_rw(E1, E2, E3, 0)
++ cpu_physical_memory_rw(E1, E2, E3, false)
+|
+- cpu_physical_memory_rw(E1, E2, E3, 1)
++ cpu_physical_memory_rw(E1, E2, E3, true)
+|
+
+- cpu_physical_memory_map(E1, E2, 0)
++ cpu_physical_memory_map(E1, E2, false)
+|
+- cpu_physical_memory_map(E1, E2, 1)
++ cpu_physical_memory_map(E1, E2, true)
+)
+
+// Use address_space_write instead of casting to non-const
+@@
+type T;
+const T *V;
+expression E1, E2, E3, E4;
+@@
+(
+- address_space_rw(E1, E2, E3, (T *)V, E4, 1)
++ address_space_write(E1, E2, E3, V, E4)
+|
+- address_space_rw(E1, E2, E3, (void *)V, E4, 1)
++ address_space_write(E1, E2, E3, V, E4)
+)
+
+// Avoid uses of address_space_rw() with a constant is_write argument.
+@@
+expression E1, E2, E3, E4, E5;
+symbol true, false;
+@@
+(
+- address_space_rw(E1, E2, E3, E4, E5, false)
++ address_space_read(E1, E2, E3, E4, E5)
+|
+- address_space_rw(E1, E2, E3, E4, E5, true)
++ address_space_write(E1, E2, E3, E4, E5)
+)
+
+// Avoid uses of cpu_physical_memory_rw() with a constant is_write argument.
+@@
+expression E1, E2, E3;
+@@
+(
+- cpu_physical_memory_rw(E1, E2, E3, false)
++ cpu_physical_memory_read(E1, E2, E3)
+|
+- cpu_physical_memory_rw(E1, E2, E3, true)
++ cpu_physical_memory_write(E1, E2, E3)
+)
+
+// Remove useless cast
+@@
+expression E1, E2, E3, E4, E5, E6;
+type T;
+@@
+(
+- address_space_rw(E1, E2, E3, (T *)(E4), E5, E6)
++ address_space_rw(E1, E2, E3, E4, E5, E6)
+|
+- address_space_read(E1, E2, E3, (T *)(E4), E5)
++ address_space_read(E1, E2, E3, E4, E5)
+|
+- address_space_write(E1, E2, E3, (T *)(E4), E5)
++ address_space_write(E1, E2, E3, E4, E5)
+|
+- address_space_write_rom(E1, E2, E3, (T *)(E4), E5)
++ address_space_write_rom(E1, E2, E3, E4, E5)
+|
+
+- cpu_physical_memory_rw(E1, (T *)(E2), E3, E4)
++ cpu_physical_memory_rw(E1, E2, E3, E4)
+|
+- cpu_physical_memory_read(E1, (T *)(E2), E3)
++ cpu_physical_memory_read(E1, E2, E3)
+|
+- cpu_physical_memory_write(E1, (T *)(E2), E3)
++ cpu_physical_memory_write(E1, E2, E3)
+|
+
+- dma_memory_read(E1, E2, (T *)(E3), E4)
++ dma_memory_read(E1, E2, E3, E4)
+|
+- dma_memory_write(E1, E2, (T *)(E3), E4)
++ dma_memory_write(E1, E2, E3, E4)
+)
diff --git a/scripts/coccinelle/inplace-byteswaps.cocci b/scripts/coccinelle/inplace-byteswaps.cocci
new file mode 100644
index 000000000..a869a90cb
--- /dev/null
+++ b/scripts/coccinelle/inplace-byteswaps.cocci
@@ -0,0 +1,65 @@
+// Replace uses of in-place byteswapping functions with calls to the
+// equivalent not-in-place functions. This is necessary to avoid
+// undefined behaviour if the expression being swapped is a field in a
+// packed struct.
+
+@@
+expression E;
+@@
+-be16_to_cpus(&E);
++E = be16_to_cpu(E);
+@@
+expression E;
+@@
+-be32_to_cpus(&E);
++E = be32_to_cpu(E);
+@@
+expression E;
+@@
+-be64_to_cpus(&E);
++E = be64_to_cpu(E);
+@@
+expression E;
+@@
+-cpu_to_be16s(&E);
++E = cpu_to_be16(E);
+@@
+expression E;
+@@
+-cpu_to_be32s(&E);
++E = cpu_to_be32(E);
+@@
+expression E;
+@@
+-cpu_to_be64s(&E);
++E = cpu_to_be64(E);
+@@
+expression E;
+@@
+-le16_to_cpus(&E);
++E = le16_to_cpu(E);
+@@
+expression E;
+@@
+-le32_to_cpus(&E);
++E = le32_to_cpu(E);
+@@
+expression E;
+@@
+-le64_to_cpus(&E);
++E = le64_to_cpu(E);
+@@
+expression E;
+@@
+-cpu_to_le16s(&E);
++E = cpu_to_le16(E);
+@@
+expression E;
+@@
+-cpu_to_le32s(&E);
++E = cpu_to_le32(E);
+@@
+expression E;
+@@
+-cpu_to_le64s(&E);
++E = cpu_to_le64(E);
diff --git a/scripts/coccinelle/memory-region-housekeeping.cocci b/scripts/coccinelle/memory-region-housekeeping.cocci
new file mode 100644
index 000000000..29651ebde
--- /dev/null
+++ b/scripts/coccinelle/memory-region-housekeeping.cocci
@@ -0,0 +1,159 @@
+/*
+ Usage:
+
+ spatch \
+ --macro-file scripts/cocci-macro-file.h \
+ --sp-file scripts/coccinelle/memory-region-housekeeping.cocci \
+ --keep-comments \
+ --in-place \
+ --dir .
+
+*/
+
+
+// Replace memory_region_init_ram(readonly) by memory_region_init_rom()
+@@
+expression E1, E2, E3, E4, E5;
+symbol true;
+@@
+(
+- memory_region_init_ram(E1, E2, E3, E4, E5);
++ memory_region_init_rom(E1, E2, E3, E4, E5);
+ ... WHEN != E1
+- memory_region_set_readonly(E1, true);
+|
+- memory_region_init_ram_nomigrate(E1, E2, E3, E4, E5);
++ memory_region_init_rom_nomigrate(E1, E2, E3, E4, E5);
+ ... WHEN != E1
+- memory_region_set_readonly(E1, true);
+)
+
+
+@possible_memory_region_init_rom@
+expression E1, E2, E3, E4, E5;
+position p;
+@@
+(
+ memory_region_init_ram@p(E1, E2, E3, E4, E5);
+ ...
+ memory_region_set_readonly(E1, true);
+|
+ memory_region_init_ram_nomigrate@p(E1, E2, E3, E4, E5);
+ ...
+ memory_region_set_readonly(E1, true);
+)
+@script:python@
+p << possible_memory_region_init_rom.p;
+@@
+cocci.print_main("potential use of memory_region_init_rom*() in ", p)
+
+
+// Do not call memory_region_set_readonly() on ROM alias
+@@
+expression ROM, E1, E2, E3, E4;
+expression ALIAS, E5, E6, E7, E8;
+@@
+(
+ memory_region_init_rom(ROM, E1, E2, E3, E4);
+|
+ memory_region_init_rom_nomigrate(ROM, E1, E2, E3, E4);
+)
+ ...
+ memory_region_init_alias(ALIAS, E5, E6, ROM, E7, E8);
+- memory_region_set_readonly(ALIAS, true);
+
+
+// Replace by-hand memory_region_init_ram_nomigrate/vmstate_register_ram
+// code sequences with use of the new memory_region_init_ram function.
+// Similarly for the _rom and _rom_device functions.
+// We don't try to replace sequences with a non-NULL owner, because
+// there are none in the tree that can be automatically converted
+// (and only a handful that can be manually converted).
+@@
+expression MR;
+expression NAME;
+expression SIZE;
+expression ERRP;
+@@
+-memory_region_init_ram_nomigrate(MR, NULL, NAME, SIZE, ERRP);
++memory_region_init_ram(MR, NULL, NAME, SIZE, ERRP);
+ ...
+-vmstate_register_ram_global(MR);
+@@
+expression MR;
+expression NAME;
+expression SIZE;
+expression ERRP;
+@@
+-memory_region_init_rom_nomigrate(MR, NULL, NAME, SIZE, ERRP);
++memory_region_init_rom(MR, NULL, NAME, SIZE, ERRP);
+ ...
+-vmstate_register_ram_global(MR);
+@@
+expression MR;
+expression OPS;
+expression OPAQUE;
+expression NAME;
+expression SIZE;
+expression ERRP;
+@@
+-memory_region_init_rom_device_nomigrate(MR, NULL, OPS, OPAQUE, NAME, SIZE, ERRP);
++memory_region_init_rom_device(MR, NULL, OPS, OPAQUE, NAME, SIZE, ERRP);
+ ...
+-vmstate_register_ram_global(MR);
+
+
+// Device is owner
+@@
+typedef DeviceState;
+identifier device_fn, dev, obj;
+expression E1, E2, E3, E4, E5;
+@@
+static void device_fn(DeviceState *dev, ...)
+{
+ ...
+ Object *obj = OBJECT(dev);
+ <+...
+(
+- memory_region_init(E1, NULL, E2, E3);
++ memory_region_init(E1, obj, E2, E3);
+|
+- memory_region_init_io(E1, NULL, E2, E3, E4, E5);
++ memory_region_init_io(E1, obj, E2, E3, E4, E5);
+|
+- memory_region_init_alias(E1, NULL, E2, E3, E4, E5);
++ memory_region_init_alias(E1, obj, E2, E3, E4, E5);
+|
+- memory_region_init_rom(E1, NULL, E2, E3, E4);
++ memory_region_init_rom(E1, obj, E2, E3, E4);
+|
+- memory_region_init_ram_flags_nomigrate(E1, NULL, E2, E3, E4, E5);
++ memory_region_init_ram_flags_nomigrate(E1, obj, E2, E3, E4, E5);
+)
+ ...+>
+}
+@@
+identifier device_fn, dev;
+expression E1, E2, E3, E4, E5;
+@@
+static void device_fn(DeviceState *dev, ...)
+{
+ <+...
+(
+- memory_region_init(E1, NULL, E2, E3);
++ memory_region_init(E1, OBJECT(dev), E2, E3);
+|
+- memory_region_init_io(E1, NULL, E2, E3, E4, E5);
++ memory_region_init_io(E1, OBJECT(dev), E2, E3, E4, E5);
+|
+- memory_region_init_alias(E1, NULL, E2, E3, E4, E5);
++ memory_region_init_alias(E1, OBJECT(dev), E2, E3, E4, E5);
+|
+- memory_region_init_rom(E1, NULL, E2, E3, E4);
++ memory_region_init_rom(E1, OBJECT(dev), E2, E3, E4);
+|
+- memory_region_init_ram_flags_nomigrate(E1, NULL, E2, E3, E4, E5);
++ memory_region_init_ram_flags_nomigrate(E1, OBJECT(dev), E2, E3, E4, E5);
+)
+ ...+>
+}
diff --git a/scripts/coccinelle/overflow_muldiv64.cocci b/scripts/coccinelle/overflow_muldiv64.cocci
new file mode 100644
index 000000000..08ec4a8de
--- /dev/null
+++ b/scripts/coccinelle/overflow_muldiv64.cocci
@@ -0,0 +1,16 @@
+// Find muldiv64(i64, i64, x) for potential overflow
+@filter@
+typedef uint64_t;
+typedef int64_t;
+{ uint64_t, int64_t, long, unsigned long } a, b;
+expression c;
+position p;
+@@
+
+muldiv64(a,b,c)@p
+
+@script:python@
+p << filter.p;
+@@
+
+cocci.print_main("potential muldiv64() overflow", p)
diff --git a/scripts/coccinelle/qobject.cocci b/scripts/coccinelle/qobject.cocci
new file mode 100644
index 000000000..9fee9c0d9
--- /dev/null
+++ b/scripts/coccinelle/qobject.cocci
@@ -0,0 +1,47 @@
+// Use QDict macros where they make sense
+@@
+expression Obj, Key, E;
+@@
+(
+- qobject_ref(QOBJECT(E));
++ qobject_ref(E);
+|
+- qobject_unref(QOBJECT(E));
++ qobject_unref(E);
+|
+- qdict_put_obj(Obj, Key, QOBJECT(E));
++ qdict_put(Obj, Key, E);
+|
+- qdict_put(Obj, Key, qnum_from_int(E));
++ qdict_put_int(Obj, Key, E);
+|
+- qdict_put(Obj, Key, qbool_from_bool(E));
++ qdict_put_bool(Obj, Key, E);
+|
+- qdict_put(Obj, Key, qstring_from_str(E));
++ qdict_put_str(Obj, Key, E);
+|
+- qdict_put(Obj, Key, qnull());
++ qdict_put_null(Obj, Key);
+)
+
+// Use QList macros where they make sense
+@@
+expression Obj, E;
+@@
+(
+- qlist_append_obj(Obj, QOBJECT(E));
++ qlist_append(Obj, E);
+|
+- qlist_append(Obj, qnum_from_int(E));
++ qlist_append_int(Obj, E);
+|
+- qlist_append(Obj, qbool_from_bool(E));
++ qlist_append_bool(Obj, E);
+|
+- qlist_append(Obj, qstring_from_str(E));
++ qlist_append_str(Obj, E);
+|
+- qlist_append(Obj, qnull());
++ qlist_append_null(Obj);
+)
diff --git a/scripts/coccinelle/qom-parent-type.cocci b/scripts/coccinelle/qom-parent-type.cocci
new file mode 100644
index 000000000..9afb3edd9
--- /dev/null
+++ b/scripts/coccinelle/qom-parent-type.cocci
@@ -0,0 +1,26 @@
+// Highlight object declarations that don't look like object class but
+// accidentally inherit from it.
+
+@match@
+identifier obj_t, fld;
+type parent_t =~ ".*Class$";
+@@
+struct obj_t {
+ parent_t fld;
+ ...
+};
+
+@script:python filter depends on match@
+obj_t << match.obj_t;
+@@
+is_class_obj = obj_t.endswith('Class')
+cocci.include_match(not is_class_obj)
+
+@replacement depends on filter@
+identifier match.obj_t, match.fld;
+type match.parent_t;
+@@
+struct obj_t {
+* parent_t fld;
+ ...
+};
diff --git a/scripts/coccinelle/remove_local_err.cocci b/scripts/coccinelle/remove_local_err.cocci
new file mode 100644
index 000000000..9261c9968
--- /dev/null
+++ b/scripts/coccinelle/remove_local_err.cocci
@@ -0,0 +1,29 @@
+// Replace unnecessary usage of local_err variable with
+// direct usage of errp argument
+
+@@
+identifier F;
+expression list ARGS;
+expression F2;
+identifier LOCAL_ERR;
+identifier ERRP;
+idexpression V;
+typedef Error;
+@@
+ F(..., Error **ERRP)
+ {
+ ...
+- Error *LOCAL_ERR;
+ ... when != LOCAL_ERR
+ when != ERRP
+(
+- F2(ARGS, &LOCAL_ERR);
+- error_propagate(ERRP, LOCAL_ERR);
++ F2(ARGS, ERRP);
+|
+- V = F2(ARGS, &LOCAL_ERR);
+- error_propagate(ERRP, LOCAL_ERR);
++ V = F2(ARGS, ERRP);
+)
+ ... when != LOCAL_ERR
+ }
diff --git a/scripts/coccinelle/remove_muldiv64.cocci b/scripts/coccinelle/remove_muldiv64.cocci
new file mode 100644
index 000000000..4c10bd57d
--- /dev/null
+++ b/scripts/coccinelle/remove_muldiv64.cocci
@@ -0,0 +1,6 @@
+// replace muldiv64(a, 1, b) by "a / b"
+@@
+expression a, b;
+@@
+-muldiv64(a, 1, b)
++a / b
diff --git a/scripts/coccinelle/return_directly.cocci b/scripts/coccinelle/return_directly.cocci
new file mode 100644
index 000000000..4cf50e75e
--- /dev/null
+++ b/scripts/coccinelle/return_directly.cocci
@@ -0,0 +1,19 @@
+// replace 'R = X; return R;' with 'return X;'
+@@
+identifier VAR;
+expression E;
+type T;
+identifier F;
+@@
+ T F(...)
+ {
+ ...
+- T VAR;
+ ... when != VAR
+
+- VAR =
++ return
+ E;
+- return VAR;
+ ... when != VAR
+ }
diff --git a/scripts/coccinelle/round.cocci b/scripts/coccinelle/round.cocci
new file mode 100644
index 000000000..ed0677328
--- /dev/null
+++ b/scripts/coccinelle/round.cocci
@@ -0,0 +1,19 @@
+// Use macro DIV_ROUND_UP instead of (((n) + (d) - 1) /(d))
+@@
+expression e1;
+expression e2;
+@@
+(
+- ((e1) + e2 - 1) / (e2)
++ DIV_ROUND_UP(e1,e2)
+|
+- ((e1) + (e2 - 1)) / (e2)
++ DIV_ROUND_UP(e1,e2)
+)
+
+@@
+expression e1;
+expression e2;
+@@
+-(DIV_ROUND_UP(e1,e2))
++DIV_ROUND_UP(e1,e2)
diff --git a/scripts/coccinelle/simplify_muldiv64.cocci b/scripts/coccinelle/simplify_muldiv64.cocci
new file mode 100644
index 000000000..3d7c9744a
--- /dev/null
+++ b/scripts/coccinelle/simplify_muldiv64.cocci
@@ -0,0 +1,11 @@
+// replace muldiv64(i32, i32, x) by (uint64_t)i32 * i32 / x
+@@
+typedef uint32_t;
+typedef int32_t;
+{ uint32_t, int32_t, int, unsigned int } a, b;
+typedef uint64_t;
+expression c;
+@@
+
+-muldiv64(a,b,c)
++(uint64_t) a * b / c
diff --git a/scripts/coccinelle/swap_muldiv64.cocci b/scripts/coccinelle/swap_muldiv64.cocci
new file mode 100644
index 000000000..b48b0d084
--- /dev/null
+++ b/scripts/coccinelle/swap_muldiv64.cocci
@@ -0,0 +1,13 @@
+// replace muldiv64(i32, i64, x) by muldiv64(i64, i32, x)
+@@
+typedef uint64_t;
+typedef int64_t;
+typedef uint32_t;
+typedef int32_t;
+{ uint32_t, int32_t, int, unsigned int } a;
+{ uint64_t, int64_t, long, unsigned long } b;
+expression c;
+@@
+
+-muldiv64(a,b,c)
++muldiv64(b,a,c)
diff --git a/scripts/coccinelle/tcg_gen_extract.cocci b/scripts/coccinelle/tcg_gen_extract.cocci
new file mode 100644
index 000000000..c10c86348
--- /dev/null
+++ b/scripts/coccinelle/tcg_gen_extract.cocci
@@ -0,0 +1,107 @@
+// optimize TCG using extract op
+//
+// Copyright: (C) 2017 Philippe Mathieu-Daudé. GPLv2+.
+// Confidence: High
+// Options: --macro-file scripts/cocci-macro-file.h
+//
+// Nikunj A Dadhania optimization:
+// http://lists.nongnu.org/archive/html/qemu-devel/2017-02/msg05211.html
+// Aurelien Jarno optimization:
+// http://lists.nongnu.org/archive/html/qemu-devel/2017-05/msg01466.html
+//
+// This script can be run either using spatch locally or via a docker image:
+//
+// $ spatch \
+// --macro-file scripts/cocci-macro-file.h \
+// --sp-file scripts/coccinelle/tcg_gen_extract.cocci \
+// --keep-comments --in-place \
+// --use-gitgrep --dir target
+//
+// $ docker run --rm -v $PWD:$PWD -w $PWD philmd/coccinelle \
+// --macro-file scripts/cocci-macro-file.h \
+// --sp-file scripts/coccinelle/tcg_gen_extract.cocci \
+// --keep-comments --in-place \
+// --use-gitgrep --dir target
+
+@initialize:python@
+@@
+import sys
+fd = sys.stderr
+def debug(msg="", trailer="\n"):
+ fd.write("[DBG] " + msg + trailer)
+def low_bits_count(value):
+ bits_count = 0
+ while (value & (1 << bits_count)):
+ bits_count += 1
+ return bits_count
+def Mn(order): # Mersenne number
+ return (1 << order) - 1
+
+@match@
+identifier ret;
+metavariable arg;
+constant ofs, msk;
+position shr_p, and_p;
+@@
+(
+ tcg_gen_shri_i32@shr_p
+|
+ tcg_gen_shri_i64@shr_p
+|
+ tcg_gen_shri_tl@shr_p
+)(ret, arg, ofs);
+... WHEN != ret
+(
+ tcg_gen_andi_i32@and_p
+|
+ tcg_gen_andi_i64@and_p
+|
+ tcg_gen_andi_tl@and_p
+)(ret, ret, msk);
+
+@script:python verify_len depends on match@
+ret_s << match.ret;
+msk_s << match.msk;
+shr_p << match.shr_p;
+extract_len;
+@@
+is_optimizable = False
+debug("candidate at %s:%s" % (shr_p[0].file, shr_p[0].line))
+try: # only eval integer, no #define like 'SR_M' (cpp did this, else some headers are missing).
+ msk_v = long(msk_s.strip("UL"), 0)
+ msk_b = low_bits_count(msk_v)
+ if msk_b == 0:
+ debug(" value: 0x%x low_bits: %d" % (msk_v, msk_b))
+ else:
+ debug(" value: 0x%x low_bits: %d [Mersenne number: 0x%x]" % (msk_v, msk_b, Mn(msk_b)))
+ is_optimizable = Mn(msk_b) == msk_v # check low_bits
+ coccinelle.extract_len = "%d" % msk_b
+ debug(" candidate %s optimizable" % ("IS" if is_optimizable else "is NOT"))
+except:
+ debug(" ERROR (check included headers?)")
+cocci.include_match(is_optimizable)
+debug()
+
+@replacement depends on verify_len@
+identifier match.ret;
+metavariable match.arg;
+constant match.ofs, match.msk;
+position match.shr_p, match.and_p;
+identifier verify_len.extract_len;
+@@
+(
+-tcg_gen_shri_i32@shr_p(ret, arg, ofs);
++tcg_gen_extract_i32(ret, arg, ofs, extract_len);
+... WHEN != ret
+-tcg_gen_andi_i32@and_p(ret, ret, msk);
+|
+-tcg_gen_shri_i64@shr_p(ret, arg, ofs);
++tcg_gen_extract_i64(ret, arg, ofs, extract_len);
+... WHEN != ret
+-tcg_gen_andi_i64@and_p(ret, ret, msk);
+|
+-tcg_gen_shri_tl@shr_p(ret, arg, ofs);
++tcg_gen_extract_tl(ret, arg, ofs, extract_len);
+... WHEN != ret
+-tcg_gen_andi_tl@and_p(ret, ret, msk);
+)
diff --git a/scripts/coccinelle/timer-del-timer-free.cocci b/scripts/coccinelle/timer-del-timer-free.cocci
new file mode 100644
index 000000000..c3cfd4280
--- /dev/null
+++ b/scripts/coccinelle/timer-del-timer-free.cocci
@@ -0,0 +1,18 @@
+// Remove superfluous timer_del() calls
+//
+// Copyright Linaro Limited 2020
+// This work is licensed under the terms of the GNU GPLv2 or later.
+//
+// spatch --macro-file scripts/cocci-macro-file.h \
+// --sp-file scripts/coccinelle/timer-del-timer-free.cocci \
+// --in-place --dir .
+//
+// The timer_free() function now implicitly calls timer_del()
+// for you, so calls to timer_del() immediately before the
+// timer_free() of the same timer can be deleted.
+
+@@
+expression T;
+@@
+-timer_del(T);
+ timer_free(T);
diff --git a/scripts/coccinelle/typecast.cocci b/scripts/coccinelle/typecast.cocci
new file mode 100644
index 000000000..be2183ee4
--- /dev/null
+++ b/scripts/coccinelle/typecast.cocci
@@ -0,0 +1,7 @@
+// Remove useless casts
+@@
+type T;
+T v;
+@@
+- (T *)&v
++ &v
diff --git a/scripts/coccinelle/use-error_fatal.cocci b/scripts/coccinelle/use-error_fatal.cocci
new file mode 100644
index 000000000..10fff0aec
--- /dev/null
+++ b/scripts/coccinelle/use-error_fatal.cocci
@@ -0,0 +1,20 @@
+@@
+type T;
+identifier FUN, RET;
+expression list ARGS;
+expression ERR, EC, FAIL;
+@@
+(
+- T RET = FUN(ARGS, &ERR);
++ T RET = FUN(ARGS, &error_fatal);
+|
+- RET = FUN(ARGS, &ERR);
++ RET = FUN(ARGS, &error_fatal);
+|
+- FUN(ARGS, &ERR);
++ FUN(ARGS, &error_fatal);
+)
+- if (FAIL) {
+- error_report_err(ERR);
+- exit(EC);
+- }