Retry cache flushes on ARMv7 devices

On ARMv7, CPU cache flushing requires a system call. This system call
can fail and return an error. This change moves to using the system
call directly (cacheflush) so flush failures can be detected and
flushing can be re-attempted. For other platforms we continue using
__builtin___clear_cache which is an intrinsic with a void return
type.

The strategy for ARMv7 is to attempt to flush the entire range
required. If this fails (a rare occurance), we visit the pages in the
flush range sequentially, first reading a byte from the page to
maximize it's chance of being resident and then flushing the cache
lines. We repeat this up to 4 times per page if there are failures.

As a final fallback, when neither approach to flushing the JIT code
cache pages succeeds, the code is not committed to the JIT code cache
as the cache lines for the new code are in an unknown state.

This complexity is necessary for the dual view JIT because the
executable range is not writable so the kernel logic does not
(appear to) anticipate the need to flush (or invalidate) cache lines
there. Previously the failing cache flush operations went undetected
and result in bad i-cache state and cause crashes. These issues have
only been reported on devices with 32-bit kernels.

Bug: 132205399
Test: art/test.py --host --jit -j32
Test: Manual (described in bug)
Change-Id: I63b56beaac610ea973def0a57118be9a2647da23
6 files changed