Merge "Restore fastboot delete-logical-partition command for VTS"
diff --git a/adb/Android.bp b/adb/Android.bp
index 139ee23..1b7a266 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -589,11 +589,9 @@
"libcrypto_utils",
"libcutils_sockets",
"libdiagnose_usb",
- "liblog",
"libmdnssd",
"libminijail",
"libprotobuf-cpp-lite",
- "libselinux",
"libssl",
],
@@ -603,6 +601,8 @@
"libadbd_auth",
"libadbd_fs",
"libcrypto",
+ "liblog",
+ "libselinux",
],
target: {
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 1186060..7c7da08 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -194,8 +194,8 @@
" generate adb public/private key; private key stored in FILE,\n"
"\n"
"scripting:\n"
- " wait-for[-TRANSPORT]-STATE\n"
- " wait for device to be in the given state\n"
+ " wait-for[-TRANSPORT]-STATE...\n"
+ " wait for device to be in a given state\n"
" STATE: device, recovery, rescue, sideload, bootloader, or disconnect\n"
" TRANSPORT: usb, local, or any [default=any]\n"
" get-state print offline | bootloader | device\n"
@@ -1057,17 +1057,16 @@
static bool wait_for_device(const char* service,
std::optional<std::chrono::milliseconds> timeout = std::nullopt) {
std::vector<std::string> components = android::base::Split(service, "-");
- if (components.size() < 3 || components.size() > 4) {
+ if (components.size() < 3) {
fprintf(stderr, "adb: couldn't parse 'wait-for' command: %s\n", service);
return false;
}
- TransportType t;
- adb_get_transport(&t, nullptr, nullptr);
-
- // Was the caller vague about what they'd like us to wait for?
- // If so, check they weren't more specific in their choice of transport type.
- if (components.size() == 3) {
+ // If the first thing after "wait-for-" wasn't a TRANSPORT, insert whatever
+ // the current transport implies.
+ if (components[2] != "usb" && components[2] != "local" && components[2] != "any") {
+ TransportType t;
+ adb_get_transport(&t, nullptr, nullptr);
auto it = components.begin() + 2;
if (t == kTransportUsb) {
components.insert(it, "usb");
@@ -1076,23 +1075,9 @@
} else {
components.insert(it, "any");
}
- } else if (components[2] != "any" && components[2] != "local" && components[2] != "usb") {
- fprintf(stderr, "adb: unknown type %s; expected 'any', 'local', or 'usb'\n",
- components[2].c_str());
- return false;
}
- if (components[3] != "any" && components[3] != "bootloader" && components[3] != "device" &&
- components[3] != "recovery" && components[3] != "rescue" && components[3] != "sideload" &&
- components[3] != "disconnect") {
- fprintf(stderr,
- "adb: unknown state %s; "
- "expected 'any', 'bootloader', 'device', 'recovery', 'rescue', 'sideload', or "
- "'disconnect'\n",
- components[3].c_str());
- return false;
- }
-
+ // Stitch it back together and send it over...
std::string cmd = format_host_command(android::base::Join(components, "-").c_str());
if (timeout) {
std::thread([timeout]() {
diff --git a/adb/client/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index cc38926..04ad536 100644
--- a/adb/client/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
@@ -1097,14 +1097,14 @@
}
};
- if (!sync_ls(sc, rpath.c_str(), callback)) {
+ if (!sync_ls(sc, rpath, callback)) {
return false;
}
// Check each symlink we found to see whether it's a file or directory.
for (copyinfo& link_ci : linklist) {
struct stat st;
- if (!sync_stat_fallback(sc, link_ci.rpath.c_str(), &st)) {
+ if (!sync_stat_fallback(sc, link_ci.rpath, &st)) {
sc.Warning("stat failed for path %s: %s", link_ci.rpath.c_str(), strerror(errno));
continue;
}
diff --git a/adb/services.cpp b/adb/services.cpp
index 853d658..d87948c 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -95,56 +95,6 @@
}
#if ADB_HOST
-struct state_info {
- TransportType transport_type;
- std::string serial;
- TransportId transport_id;
- ConnectionState state;
-};
-
-static void wait_for_state(unique_fd fd, state_info* sinfo) {
- D("wait_for_state %d", sinfo->state);
-
- while (true) {
- bool is_ambiguous = false;
- std::string error = "unknown error";
- const char* serial = sinfo->serial.length() ? sinfo->serial.c_str() : nullptr;
- atransport* t = acquire_one_transport(sinfo->transport_type, serial, sinfo->transport_id,
- &is_ambiguous, &error);
- if (sinfo->state == kCsOffline) {
- // wait-for-disconnect uses kCsOffline, we don't actually want to wait for 'offline'.
- if (t == nullptr) {
- SendOkay(fd);
- break;
- }
- } else if (t != nullptr &&
- (sinfo->state == kCsAny || sinfo->state == t->GetConnectionState())) {
- SendOkay(fd);
- break;
- }
-
- if (!is_ambiguous) {
- adb_pollfd pfd = {.fd = fd.get(), .events = POLLIN};
- int rc = adb_poll(&pfd, 1, 100);
- if (rc < 0) {
- SendFail(fd, error);
- break;
- } else if (rc > 0 && (pfd.revents & POLLHUP) != 0) {
- // The other end of the socket is closed, probably because the other side was
- // terminated, bail out.
- break;
- }
-
- // Try again...
- } else {
- SendFail(fd, error);
- break;
- }
- }
-
- D("wait_for_state is done");
-}
-
void connect_emulator(const std::string& port_spec, std::string* response) {
std::vector<std::string> pieces = android::base::Split(port_spec, ",");
if (pieces.size() != 2) {
@@ -201,6 +151,80 @@
adb_wifi_pair_device(host, password, response);
SendProtocolString(fd.get(), response);
}
+
+static void wait_service(unique_fd fd, std::string serial, TransportId transport_id,
+ std::string spec) {
+ std::vector<std::string> components = android::base::Split(spec, "-");
+ if (components.size() < 2) {
+ SendFail(fd, "short wait-for-: " + spec);
+ return;
+ }
+
+ TransportType transport_type;
+ if (components[0] == "local") {
+ transport_type = kTransportLocal;
+ } else if (components[0] == "usb") {
+ transport_type = kTransportUsb;
+ } else if (components[0] == "any") {
+ transport_type = kTransportAny;
+ } else {
+ SendFail(fd, "bad wait-for- transport: " + spec);
+ return;
+ }
+
+ std::vector<ConnectionState> states;
+ for (size_t i = 1; i < components.size(); ++i) {
+ if (components[i] == "device") {
+ states.push_back(kCsDevice);
+ } else if (components[i] == "recovery") {
+ states.push_back(kCsRecovery);
+ } else if (components[i] == "rescue") {
+ states.push_back(kCsRescue);
+ } else if (components[i] == "sideload") {
+ states.push_back(kCsSideload);
+ } else if (components[i] == "bootloader") {
+ states.push_back(kCsBootloader);
+ } else if (components[i] == "any") {
+ states.push_back(kCsAny);
+ } else if (components[i] == "disconnect") {
+ states.push_back(kCsOffline);
+ } else {
+ SendFail(fd, "bad wait-for- state: " + spec);
+ return;
+ }
+ }
+
+ while (true) {
+ bool is_ambiguous = false;
+ std::string error = "unknown error";
+ atransport* t =
+ acquire_one_transport(transport_type, !serial.empty() ? serial.c_str() : nullptr,
+ transport_id, &is_ambiguous, &error);
+
+ for (const auto& state : states) {
+ // wait-for-disconnect uses kCsOffline, we don't actually want to wait for 'offline'.
+ if ((t == nullptr && state == kCsOffline) || (t != nullptr && state == kCsAny) ||
+ (t != nullptr && state == t->GetConnectionState())) {
+ SendOkay(fd);
+ return;
+ }
+ }
+
+ if (is_ambiguous) {
+ SendFail(fd, error);
+ return;
+ }
+
+ // Sleep before retrying.
+ adb_pollfd pfd = {.fd = fd.get(), .events = POLLIN};
+ if (adb_poll(&pfd, 1, 100) != 0) {
+ // The other end of the socket is closed, probably because the
+ // client terminated. Bail out.
+ SendFail(fd, error);
+ return;
+ }
+ }
+}
#endif
#if ADB_HOST
@@ -211,45 +235,10 @@
} else if (name == "track-devices-l") {
return create_device_tracker(true);
} else if (android::base::ConsumePrefix(&name, "wait-for-")) {
- std::shared_ptr<state_info> sinfo = std::make_shared<state_info>();
- if (sinfo == nullptr) {
- fprintf(stderr, "couldn't allocate state_info: %s", strerror(errno));
- return nullptr;
- }
-
- sinfo->serial = serial;
- sinfo->transport_id = transport_id;
-
- if (android::base::ConsumePrefix(&name, "local")) {
- sinfo->transport_type = kTransportLocal;
- } else if (android::base::ConsumePrefix(&name, "usb")) {
- sinfo->transport_type = kTransportUsb;
- } else if (android::base::ConsumePrefix(&name, "any")) {
- sinfo->transport_type = kTransportAny;
- } else {
- return nullptr;
- }
-
- if (name == "-device") {
- sinfo->state = kCsDevice;
- } else if (name == "-recovery") {
- sinfo->state = kCsRecovery;
- } else if (name == "-rescue") {
- sinfo->state = kCsRescue;
- } else if (name == "-sideload") {
- sinfo->state = kCsSideload;
- } else if (name == "-bootloader") {
- sinfo->state = kCsBootloader;
- } else if (name == "-any") {
- sinfo->state = kCsAny;
- } else if (name == "-disconnect") {
- sinfo->state = kCsOffline;
- } else {
- return nullptr;
- }
-
- unique_fd fd = create_service_thread(
- "wait", [sinfo](unique_fd fd) { wait_for_state(std::move(fd), sinfo.get()); });
+ std::string spec(name);
+ unique_fd fd =
+ create_service_thread("wait", std::bind(wait_service, std::placeholders::_1,
+ std::string(serial), transport_id, spec));
return create_local_socket(std::move(fd));
} else if (android::base::ConsumePrefix(&name, "connect:")) {
std::string host(name);
diff --git a/base/liblog_symbols.cpp b/base/liblog_symbols.cpp
index d5dfcd2..8d59179 100644
--- a/base/liblog_symbols.cpp
+++ b/base/liblog_symbols.cpp
@@ -16,14 +16,20 @@
#include "liblog_symbols.h"
-#if defined(__ANDROID__) && !defined(NO_LIBLOG_DLSYM)
+#if defined(__ANDROID__)
+#if !defined(NO_LIBLOG_DLSYM) || defined(__ANDROID_APEX__)
+#define USE_DLSYM
+#endif
+#endif
+
+#ifdef USE_DLSYM
#include <dlfcn.h>
#endif
namespace android {
namespace base {
-#if defined(__ANDROID__) && !defined(NO_LIBLOG_DLSYM)
+#ifdef USE_DLSYM
const std::optional<LibLogFunctions>& GetLibLogFunctions() {
static std::optional<LibLogFunctions> liblog_functions = []() -> std::optional<LibLogFunctions> {
diff --git a/base/liblog_symbols.h b/base/liblog_symbols.h
index d3134e9..b4ab06a 100644
--- a/base/liblog_symbols.h
+++ b/base/liblog_symbols.h
@@ -36,8 +36,8 @@
void (*__android_log_set_aborter)(__android_aborter_function aborter);
void (*__android_log_call_aborter)(const char* abort_message);
void (*__android_log_default_aborter)(const char* abort_message);
- int (*__android_log_set_minimum_priority)(int priority);
- int (*__android_log_get_minimum_priority)();
+ int32_t (*__android_log_set_minimum_priority)(int32_t priority);
+ int32_t (*__android_log_get_minimum_priority)();
void (*__android_log_set_default_tag)(const char* tag);
};
diff --git a/base/logging.cpp b/base/logging.cpp
index 9360a56..9a6e0fb 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -118,7 +118,7 @@
}
#endif
-static LogId log_id_tToLogId(int buffer_id) {
+static LogId log_id_tToLogId(int32_t buffer_id) {
switch (buffer_id) {
case LOG_ID_MAIN:
return MAIN;
@@ -134,7 +134,7 @@
}
}
-static int LogIdTolog_id_t(LogId log_id) {
+static int32_t LogIdTolog_id_t(LogId log_id) {
switch (log_id) {
case MAIN:
return LOG_ID_MAIN;
@@ -171,7 +171,7 @@
}
}
-static android_LogPriority LogSeverityToPriority(LogSeverity severity) {
+static int32_t LogSeverityToPriority(LogSeverity severity) {
switch (severity) {
case VERBOSE:
return ANDROID_LOG_VERBOSE;
@@ -333,12 +333,12 @@
void LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag,
const char* file, unsigned int line,
const char* message) {
- android_LogPriority priority = LogSeverityToPriority(severity);
+ int32_t priority = LogSeverityToPriority(severity);
if (id == DEFAULT) {
id = default_log_id_;
}
- int lg_id = LogIdTolog_id_t(id);
+ int32_t lg_id = LogIdTolog_id_t(id);
char log_message_with_file[4068]; // LOGGER_ENTRY_MAX_PAYLOAD, not available in the NDK.
if (priority == ANDROID_LOG_FATAL && file != nullptr) {
@@ -574,7 +574,7 @@
void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity severity, const char* tag,
const char* message) {
static auto& liblog_functions = GetLibLogFunctions();
- auto priority = LogSeverityToPriority(severity);
+ int32_t priority = LogSeverityToPriority(severity);
if (liblog_functions) {
__android_logger_data logger_data = {
sizeof(__android_logger_data), LOG_ID_DEFAULT, priority, tag, file, line};
@@ -608,7 +608,7 @@
// we need to fall back to using gMinimumLogSeverity, since __android_log_is_loggable() will not
// take into consideration the value from SetMinimumLogSeverity().
if (liblog_functions) {
- int priority = LogSeverityToPriority(severity);
+ int32_t priority = LogSeverityToPriority(severity);
return __android_log_is_loggable(priority, tag, ANDROID_LOG_INFO);
} else {
return severity >= gMinimumLogSeverity;
@@ -618,7 +618,7 @@
LogSeverity SetMinimumLogSeverity(LogSeverity new_severity) {
static auto& liblog_functions = GetLibLogFunctions();
if (liblog_functions) {
- auto priority = LogSeverityToPriority(new_severity);
+ int32_t priority = LogSeverityToPriority(new_severity);
return PriorityToLogSeverity(liblog_functions->__android_log_set_minimum_priority(priority));
} else {
LogSeverity old_severity = gMinimumLogSeverity;
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 0089989..c0c0e99 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1588,76 +1588,58 @@
}
}
-static std::string ResolveBlockDevice(const std::string& block_device) {
+static bool UnwindDmDeviceStack(const std::string& block_device,
+ std::vector<std::string>* dm_stack) {
if (!StartsWith(block_device, "/dev/block/")) {
LWARNING << block_device << " is not a block device";
- return block_device;
+ return false;
}
- std::string name = block_device.substr(5);
- if (!StartsWith(name, "block/dm-")) {
- // Not a dm-device, but might be a symlink. Optimistically try to readlink.
- std::string result;
- if (Readlink(block_device, &result)) {
- return result;
- } else if (errno == EINVAL) {
- // After all, it wasn't a symlink.
- return block_device;
- } else {
- LERROR << "Failed to readlink " << block_device;
- return "";
- }
- }
- // It's a dm-device, let's find what's inside!
- std::string sys_dir = "/sys/" + name;
+ std::string current = block_device;
+ DeviceMapper& dm = DeviceMapper::Instance();
while (true) {
- std::string slaves_dir = sys_dir + "/slaves";
- std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(slaves_dir.c_str()), closedir);
- if (!dir) {
- LERROR << "Failed to open " << slaves_dir;
- return "";
+ dm_stack->push_back(current);
+ if (!dm.IsDmBlockDevice(current)) {
+ break;
}
- std::string sub_device_name = "";
- for (auto entry = readdir(dir.get()); entry; entry = readdir(dir.get())) {
- if (entry->d_type != DT_LNK) continue;
- if (!sub_device_name.empty()) {
- LERROR << "Too many slaves in " << slaves_dir;
- return "";
- }
- sub_device_name = entry->d_name;
+ auto parent = dm.GetParentBlockDeviceByPath(current);
+ if (!parent) {
+ return false;
}
- if (sub_device_name.empty()) {
- LERROR << "No slaves in " << slaves_dir;
- return "";
- }
- if (!StartsWith(sub_device_name, "dm-")) {
- // Not a dm-device! We can stop now.
- return "/dev/block/" + sub_device_name;
- }
- // Still a dm-device, keep digging.
- sys_dir = "/sys/block/" + sub_device_name;
+ current = *parent;
}
+ return true;
}
FstabEntry* fs_mgr_get_mounted_entry_for_userdata(Fstab* fstab, const FstabEntry& mounted_entry) {
- std::string resolved_block_device = ResolveBlockDevice(mounted_entry.blk_device);
- if (resolved_block_device.empty()) {
+ if (mounted_entry.mount_point != "/data") {
+ LERROR << mounted_entry.mount_point << " is not /data";
return nullptr;
}
- LINFO << "/data is mounted on " << resolved_block_device;
+ std::vector<std::string> dm_stack;
+ if (!UnwindDmDeviceStack(mounted_entry.blk_device, &dm_stack)) {
+ LERROR << "Failed to unwind dm-device stack for " << mounted_entry.blk_device;
+ return nullptr;
+ }
for (auto& entry : *fstab) {
if (entry.mount_point != "/data") {
continue;
}
std::string block_device;
- if (!Readlink(entry.blk_device, &block_device)) {
- LWARNING << "Failed to readlink " << entry.blk_device;
+ if (entry.fs_mgr_flags.logical) {
+ if (!fs_mgr_update_logical_partition(&entry)) {
+ LERROR << "Failed to update logic partition " << entry.blk_device;
+ continue;
+ }
+ block_device = entry.blk_device;
+ } else if (!Readlink(entry.blk_device, &block_device)) {
+ PWARNING << "Failed to read link " << entry.blk_device;
block_device = entry.blk_device;
}
- if (block_device == resolved_block_device) {
+ if (std::find(dm_stack.begin(), dm_stack.end(), block_device) != dm_stack.end()) {
return &entry;
}
}
- LERROR << "Didn't find entry that was used to mount /data";
+ LERROR << "Didn't find entry that was used to mount /data onto " << mounted_entry.blk_device;
return nullptr;
}
diff --git a/fs_mgr/libfiemap/Android.bp b/fs_mgr/libfiemap/Android.bp
index 2fd463c..ac589c7 100644
--- a/fs_mgr/libfiemap/Android.bp
+++ b/fs_mgr/libfiemap/Android.bp
@@ -45,6 +45,7 @@
whole_static_libs: [
"gsi_aidl_interface-cpp",
"libgsi",
+ "libgsid",
],
shared_libs: [
"libbinder",
diff --git a/fs_mgr/libfiemap/binder.cpp b/fs_mgr/libfiemap/binder.cpp
index 5e29d4e..c8516ab 100644
--- a/fs_mgr/libfiemap/binder.cpp
+++ b/fs_mgr/libfiemap/binder.cpp
@@ -19,9 +19,9 @@
#include <android-base/properties.h>
#include <android/gsi/BnProgressCallback.h>
#include <android/gsi/IGsiService.h>
-#include <binder/IServiceManager.h>
#include <libfiemap/image_manager.h>
#include <libgsi/libgsi.h>
+#include <libgsi/libgsid.h>
namespace android {
namespace fiemap {
@@ -224,19 +224,9 @@
return false;
}
-static sp<IGsiService> GetGsiService() {
- auto sm = android::defaultServiceManager();
- auto name = android::String16(kGsiServiceName);
- android::sp<android::IBinder> res = sm->waitForService(name);
- if (res) {
- return android::interface_cast<IGsiService>(res);
- }
- return nullptr;
-}
-
std::unique_ptr<IImageManager> IImageManager::Open(
const std::string& dir, const std::chrono::milliseconds& /*timeout_ms*/) {
- android::sp<IGsiService> service = GetGsiService();
+ android::sp<IGsiService> service = android::gsi::GetGsiService();
android::sp<IImageService> manager;
auto status = service->openImageService(dir, &manager);
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 68a81ed..957c26c 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -74,7 +74,8 @@
static constexpr const std::string_view kCowGroupName = "cow";
-bool SourceCopyOperationIsClone(const chromeos_update_engine::InstallOperation& operation);
+bool OptimizeSourceCopyOperation(const chromeos_update_engine::InstallOperation& operation,
+ chromeos_update_engine::InstallOperation* optimized);
enum class CreateResult : unsigned int {
ERROR,
diff --git a/fs_mgr/libsnapshot/partition_cow_creator.cpp b/fs_mgr/libsnapshot/partition_cow_creator.cpp
index 61f5c0c..efdb59f 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator.cpp
+++ b/fs_mgr/libsnapshot/partition_cow_creator.cpp
@@ -62,17 +62,68 @@
return false;
}
-bool SourceCopyOperationIsClone(const InstallOperation& operation) {
- using ChromeOSExtent = chromeos_update_engine::Extent;
- if (operation.src_extents().size() != operation.dst_extents().size()) {
+bool OptimizeSourceCopyOperation(const InstallOperation& operation, InstallOperation* optimized) {
+ if (operation.type() != InstallOperation::SOURCE_COPY) {
return false;
}
- return std::equal(operation.src_extents().begin(), operation.src_extents().end(),
- operation.dst_extents().begin(),
- [](const ChromeOSExtent& src, const ChromeOSExtent& dst) {
- return src.start_block() == dst.start_block() &&
- src.num_blocks() == dst.num_blocks();
- });
+
+ optimized->Clear();
+ optimized->set_type(InstallOperation::SOURCE_COPY);
+
+ const auto& src_extents = operation.src_extents();
+ const auto& dst_extents = operation.dst_extents();
+
+ // If input is empty, skip by returning an empty result.
+ if (src_extents.empty() && dst_extents.empty()) {
+ return true;
+ }
+
+ auto s_it = src_extents.begin();
+ auto d_it = dst_extents.begin();
+ uint64_t s_offset = 0; // offset within *s_it
+ uint64_t d_offset = 0; // offset within *d_it
+ bool is_optimized = false;
+
+ while (s_it != src_extents.end() || d_it != dst_extents.end()) {
+ if (s_it == src_extents.end() || d_it == dst_extents.end()) {
+ LOG(ERROR) << "number of blocks do not equal in src_extents and dst_extents";
+ return false;
+ }
+ if (s_it->num_blocks() <= s_offset || d_it->num_blocks() <= d_offset) {
+ LOG(ERROR) << "Offset goes out of bounds.";
+ return false;
+ }
+
+ // Check the next |step| blocks, where |step| is the min of remaining blocks in the current
+ // source extent and current destination extent.
+ auto s_step = s_it->num_blocks() - s_offset;
+ auto d_step = d_it->num_blocks() - d_offset;
+ auto step = std::min(s_step, d_step);
+
+ bool moved = s_it->start_block() + s_offset != d_it->start_block() + d_offset;
+ if (moved) {
+ // If the next |step| blocks are not copied to the same location, add them to result.
+ AppendExtent(optimized->mutable_src_extents(), s_it->start_block() + s_offset, step);
+ AppendExtent(optimized->mutable_dst_extents(), d_it->start_block() + d_offset, step);
+ } else {
+ // The next |step| blocks are optimized out.
+ is_optimized = true;
+ }
+
+ // Advance offsets by |step|, and go to the next non-empty extent if the current extent is
+ // depleted.
+ s_offset += step;
+ d_offset += step;
+ while (s_it != src_extents.end() && s_offset >= s_it->num_blocks()) {
+ ++s_it;
+ s_offset = 0;
+ }
+ while (d_it != dst_extents.end() && d_offset >= d_it->num_blocks()) {
+ ++d_it;
+ d_offset = 0;
+ }
+ }
+ return is_optimized;
}
void WriteExtent(DmSnapCowSizeCalculator* sc, const chromeos_update_engine::Extent& de,
@@ -101,12 +152,15 @@
if (operations == nullptr) return sc.cow_size_bytes();
for (const auto& iop : *operations) {
- // Do not allocate space for operations that are going to be skipped
+ const InstallOperation* written_op = &iop;
+ InstallOperation buf;
+ // Do not allocate space for extents that are going to be skipped
// during OTA application.
- if (iop.type() == InstallOperation::SOURCE_COPY && SourceCopyOperationIsClone(iop))
- continue;
+ if (iop.type() == InstallOperation::SOURCE_COPY && OptimizeSourceCopyOperation(iop, &buf)) {
+ written_op = &buf;
+ }
- for (const auto& de : iop.dst_extents()) {
+ for (const auto& de : written_op->dst_extents()) {
WriteExtent(&sc, de, sectors_per_block);
}
}
diff --git a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
index 9da3f05..526f874 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
+++ b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
@@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <optional>
+#include <tuple>
+
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <libdm/dm.h>
@@ -26,6 +29,13 @@
using namespace android::fs_mgr;
+using chromeos_update_engine::InstallOperation;
+using UeExtent = chromeos_update_engine::Extent;
+using google::protobuf::RepeatedPtrField;
+using ::testing::Matches;
+using ::testing::Pointwise;
+using ::testing::Truly;
+
namespace android {
namespace snapshot {
@@ -213,5 +223,76 @@
}
}
+void BlocksToExtents(const std::vector<uint64_t>& blocks,
+ google::protobuf::RepeatedPtrField<UeExtent>* extents) {
+ for (uint64_t block : blocks) {
+ AppendExtent(extents, block, 1);
+ }
+}
+
+template <typename T>
+std::vector<uint64_t> ExtentsToBlocks(const T& extents) {
+ std::vector<uint64_t> blocks;
+ for (const auto& extent : extents) {
+ for (uint64_t offset = 0; offset < extent.num_blocks(); ++offset) {
+ blocks.push_back(extent.start_block() + offset);
+ }
+ }
+ return blocks;
+}
+
+InstallOperation CreateCopyOp(const std::vector<uint64_t>& src_blocks,
+ const std::vector<uint64_t>& dst_blocks) {
+ InstallOperation op;
+ op.set_type(InstallOperation::SOURCE_COPY);
+ BlocksToExtents(src_blocks, op.mutable_src_extents());
+ BlocksToExtents(dst_blocks, op.mutable_dst_extents());
+ return op;
+}
+
+// ExtentEqual(tuple<UeExtent, UeExtent>)
+MATCHER(ExtentEqual, "") {
+ auto&& [a, b] = arg;
+ return a.start_block() == b.start_block() && a.num_blocks() == b.num_blocks();
+}
+
+struct OptimizeOperationTestParam {
+ InstallOperation input;
+ std::optional<InstallOperation> expected_output;
+};
+
+class OptimizeOperationTest : public ::testing::TestWithParam<OptimizeOperationTestParam> {};
+TEST_P(OptimizeOperationTest, Test) {
+ InstallOperation actual_output;
+ EXPECT_EQ(GetParam().expected_output.has_value(),
+ OptimizeSourceCopyOperation(GetParam().input, &actual_output))
+ << "OptimizeSourceCopyOperation should "
+ << (GetParam().expected_output.has_value() ? "succeed" : "fail");
+ if (!GetParam().expected_output.has_value()) return;
+ EXPECT_THAT(actual_output.src_extents(),
+ Pointwise(ExtentEqual(), GetParam().expected_output->src_extents()));
+ EXPECT_THAT(actual_output.dst_extents(),
+ Pointwise(ExtentEqual(), GetParam().expected_output->dst_extents()));
+}
+
+std::vector<OptimizeOperationTestParam> GetOptimizeOperationTestParams() {
+ return {
+ {CreateCopyOp({}, {}), CreateCopyOp({}, {})},
+ {CreateCopyOp({1, 2, 4}, {1, 2, 4}), CreateCopyOp({}, {})},
+ {CreateCopyOp({1, 2, 3}, {4, 5, 6}), std::nullopt},
+ {CreateCopyOp({3, 2}, {1, 2}), CreateCopyOp({3}, {1})},
+ {CreateCopyOp({5, 6, 3, 4, 1, 2}, {1, 2, 3, 4, 5, 6}),
+ CreateCopyOp({5, 6, 1, 2}, {1, 2, 5, 6})},
+ {CreateCopyOp({1, 2, 3, 5, 5, 6}, {5, 6, 3, 4, 1, 2}),
+ CreateCopyOp({1, 2, 5, 5, 6}, {5, 6, 4, 1, 2})},
+ {CreateCopyOp({1, 2, 5, 6, 9, 10}, {1, 4, 5, 6, 7, 8}),
+ CreateCopyOp({2, 9, 10}, {4, 7, 8})},
+ {CreateCopyOp({2, 3, 3, 4, 4}, {1, 2, 3, 4, 5}), CreateCopyOp({2, 3, 4}, {1, 2, 5})},
+ };
+}
+
+INSTANTIATE_TEST_CASE_P(Snapshot, OptimizeOperationTest,
+ ::testing::ValuesIn(GetOptimizeOperationTestParams()));
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/utility.cpp b/fs_mgr/libsnapshot/utility.cpp
index 3318b33..d32b61e 100644
--- a/fs_mgr/libsnapshot/utility.cpp
+++ b/fs_mgr/libsnapshot/utility.cpp
@@ -34,6 +34,7 @@
using android::fs_mgr::MetadataBuilder;
using android::fs_mgr::Partition;
using android::fs_mgr::ReadDefaultFstab;
+using google::protobuf::RepeatedPtrField;
namespace android {
namespace snapshot {
@@ -166,5 +167,20 @@
return os << std::put_time(&now, "%Y%m%d-%H%M%S");
}
+void AppendExtent(RepeatedPtrField<chromeos_update_engine::Extent>* extents, uint64_t start_block,
+ uint64_t num_blocks) {
+ if (extents->size() > 0) {
+ auto last_extent = extents->rbegin();
+ auto next_block = last_extent->start_block() + last_extent->num_blocks();
+ if (start_block == next_block) {
+ last_extent->set_num_blocks(last_extent->num_blocks() + num_blocks);
+ return;
+ }
+ }
+ auto* new_extent = extents->Add();
+ new_extent->set_start_block(start_block);
+ new_extent->set_num_blocks(num_blocks);
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/utility.h b/fs_mgr/libsnapshot/utility.h
index 90ad0fe..e69bdad 100644
--- a/fs_mgr/libsnapshot/utility.h
+++ b/fs_mgr/libsnapshot/utility.h
@@ -125,5 +125,9 @@
struct Now {};
std::ostream& operator<<(std::ostream& os, const Now&);
+// Append to |extents|. Merged into the last element if possible.
+void AppendExtent(google::protobuf::RepeatedPtrField<chromeos_update_engine::Extent>* extents,
+ uint64_t start_block, uint64_t num_blocks);
+
} // namespace snapshot
} // namespace android
diff --git a/init/Android.bp b/init/Android.bp
index 3bb08db..72a7bfe 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -81,6 +81,7 @@
"-Wextra",
"-Wno-unused-parameter",
"-Werror",
+ "-Wthread-safety",
"-DALLOW_FIRST_STAGE_CONSOLE=0",
"-DALLOW_LOCAL_PROP_OVERRIDE=0",
"-DALLOW_PERMISSIVE_SELINUX=0",
diff --git a/init/action_manager.cpp b/init/action_manager.cpp
index ebca762..b45f5cd 100644
--- a/init/action_manager.cpp
+++ b/init/action_manager.cpp
@@ -41,10 +41,12 @@
}
void ActionManager::QueueEventTrigger(const std::string& trigger) {
+ auto lock = std::lock_guard{event_queue_lock_};
event_queue_.emplace(trigger);
}
void ActionManager::QueuePropertyChange(const std::string& name, const std::string& value) {
+ auto lock = std::lock_guard{event_queue_lock_};
event_queue_.emplace(std::make_pair(name, value));
}
@@ -53,6 +55,7 @@
}
void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
+ auto lock = std::lock_guard{event_queue_lock_};
auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name,
std::map<std::string, std::string>{});
action->AddCommand(std::move(func), {name}, 0);
@@ -62,15 +65,18 @@
}
void ActionManager::ExecuteOneCommand() {
- // Loop through the event queue until we have an action to execute
- while (current_executing_actions_.empty() && !event_queue_.empty()) {
- for (const auto& action : actions_) {
- if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
- event_queue_.front())) {
- current_executing_actions_.emplace(action.get());
+ {
+ auto lock = std::lock_guard{event_queue_lock_};
+ // Loop through the event queue until we have an action to execute
+ while (current_executing_actions_.empty() && !event_queue_.empty()) {
+ for (const auto& action : actions_) {
+ if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
+ event_queue_.front())) {
+ current_executing_actions_.emplace(action.get());
+ }
}
+ event_queue_.pop();
}
- event_queue_.pop();
}
if (current_executing_actions_.empty()) {
@@ -103,6 +109,7 @@
}
bool ActionManager::HasMoreCommands() const {
+ auto lock = std::lock_guard{event_queue_lock_};
return !current_executing_actions_.empty() || !event_queue_.empty();
}
@@ -113,6 +120,7 @@
}
void ActionManager::ClearQueue() {
+ auto lock = std::lock_guard{event_queue_lock_};
// We are shutting down so don't claim the oneshot builtin actions back
current_executing_actions_ = {};
event_queue_ = {};
diff --git a/init/action_manager.h b/init/action_manager.h
index a2b95ac..b6f93d9 100644
--- a/init/action_manager.h
+++ b/init/action_manager.h
@@ -16,9 +16,12 @@
#pragma once
+#include <mutex>
#include <string>
#include <vector>
+#include <android-base/thread_annotations.h>
+
#include "action.h"
#include "builtins.h"
@@ -48,7 +51,9 @@
void operator=(ActionManager const&) = delete;
std::vector<std::unique_ptr<Action>> actions_;
- std::queue<std::variant<EventTrigger, PropertyChange, BuiltinAction>> event_queue_;
+ std::queue<std::variant<EventTrigger, PropertyChange, BuiltinAction>> event_queue_
+ GUARDED_BY(event_queue_lock_);
+ mutable std::mutex event_queue_lock_;
std::queue<const Action*> current_executing_actions_;
std::size_t current_command_;
};
diff --git a/init/init.cpp b/init/init.cpp
index a7518fc..b29dfa3 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -33,7 +33,9 @@
#include <functional>
#include <map>
#include <memory>
+#include <mutex>
#include <optional>
+#include <thread>
#include <vector>
#include <android-base/chrono_utils.h>
@@ -95,14 +97,155 @@
static int signal_fd = -1;
static int property_fd = -1;
-static std::unique_ptr<Timer> waiting_for_prop(nullptr);
-static std::string wait_prop_name;
-static std::string wait_prop_value;
-static std::string shutdown_command;
-static bool do_shutdown = false;
-
static std::unique_ptr<Subcontext> subcontext;
+struct PendingControlMessage {
+ std::string message;
+ std::string name;
+ pid_t pid;
+ int fd;
+};
+static std::mutex pending_control_messages_lock;
+static std::queue<PendingControlMessage> pending_control_messages;
+
+// Init epolls various FDs to wait for various inputs. It previously waited on property changes
+// with a blocking socket that contained the information related to the change, however, it was easy
+// to fill that socket and deadlock the system. Now we use locks to handle the property changes
+// directly in the property thread, however we still must wake the epoll to inform init that there
+// is a change to process, so we use this FD. It is non-blocking, since we do not care how many
+// times WakeEpoll() is called, only that the epoll will wake.
+static int wake_epoll_fd = -1;
+static void InstallInitNotifier(Epoll* epoll) {
+ int sockets[2];
+ if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, sockets) != 0) {
+ PLOG(FATAL) << "Failed to socketpair() between property_service and init";
+ }
+ int epoll_fd = sockets[0];
+ wake_epoll_fd = sockets[1];
+
+ auto drain_socket = [epoll_fd] {
+ char buf[512];
+ while (read(epoll_fd, buf, sizeof(buf)) > 0) {
+ }
+ };
+
+ if (auto result = epoll->RegisterHandler(epoll_fd, drain_socket); !result.ok()) {
+ LOG(FATAL) << result.error();
+ }
+}
+
+static void WakeEpoll() {
+ constexpr char value[] = "1";
+ write(wake_epoll_fd, value, sizeof(value));
+}
+
+static class PropWaiterState {
+ public:
+ bool StartWaiting(const char* name, const char* value) {
+ auto lock = std::lock_guard{lock_};
+ if (waiting_for_prop_) {
+ return false;
+ }
+ if (GetProperty(name, "") != value) {
+ // Current property value is not equal to expected value
+ wait_prop_name_ = name;
+ wait_prop_value_ = value;
+ waiting_for_prop_.reset(new Timer());
+ } else {
+ LOG(INFO) << "start_waiting_for_property(\"" << name << "\", \"" << value
+ << "\"): already set";
+ }
+ return true;
+ }
+
+ void ResetWaitForProp() {
+ auto lock = std::lock_guard{lock_};
+ ResetWaitForPropLocked();
+ }
+
+ void CheckAndResetWait(const std::string& name, const std::string& value) {
+ auto lock = std::lock_guard{lock_};
+ // We always record how long init waited for ueventd to tell us cold boot finished.
+ // If we aren't waiting on this property, it means that ueventd finished before we even
+ // started to wait.
+ if (name == kColdBootDoneProp) {
+ auto time_waited = waiting_for_prop_ ? waiting_for_prop_->duration().count() : 0;
+ std::thread([time_waited] {
+ SetProperty("ro.boottime.init.cold_boot_wait", std::to_string(time_waited));
+ }).detach();
+ }
+
+ if (waiting_for_prop_) {
+ if (wait_prop_name_ == name && wait_prop_value_ == value) {
+ LOG(INFO) << "Wait for property '" << wait_prop_name_ << "=" << wait_prop_value_
+ << "' took " << *waiting_for_prop_;
+ ResetWaitForPropLocked();
+ WakeEpoll();
+ }
+ }
+ }
+
+ // This is not thread safe because it releases the lock when it returns, so the waiting state
+ // may change. However, we only use this function to prevent running commands in the main
+ // thread loop when we are waiting, so we do not care about false positives; only false
+ // negatives. StartWaiting() and this function are always called from the same thread, so false
+ // negatives are not possible and therefore we're okay.
+ bool MightBeWaiting() {
+ auto lock = std::lock_guard{lock_};
+ return static_cast<bool>(waiting_for_prop_);
+ }
+
+ private:
+ void ResetWaitForPropLocked() {
+ wait_prop_name_.clear();
+ wait_prop_value_.clear();
+ waiting_for_prop_.reset();
+ }
+
+ std::mutex lock_;
+ std::unique_ptr<Timer> waiting_for_prop_{nullptr};
+ std::string wait_prop_name_;
+ std::string wait_prop_value_;
+
+} prop_waiter_state;
+
+bool start_waiting_for_property(const char* name, const char* value) {
+ return prop_waiter_state.StartWaiting(name, value);
+}
+
+void ResetWaitForProp() {
+ prop_waiter_state.ResetWaitForProp();
+}
+
+static class ShutdownState {
+ public:
+ void TriggerShutdown(const std::string& command) {
+ // We can't call HandlePowerctlMessage() directly in this function,
+ // because it modifies the contents of the action queue, which can cause the action queue
+ // to get into a bad state if this function is called from a command being executed by the
+ // action queue. Instead we set this flag and ensure that shutdown happens before the next
+ // command is run in the main init loop.
+ auto lock = std::lock_guard{shutdown_command_lock_};
+ shutdown_command_ = command;
+ do_shutdown_ = true;
+ WakeEpoll();
+ }
+
+ std::optional<std::string> CheckShutdown() {
+ auto lock = std::lock_guard{shutdown_command_lock_};
+ if (do_shutdown_ && !IsShuttingDown()) {
+ do_shutdown_ = false;
+ return shutdown_command_;
+ }
+ return {};
+ }
+
+ private:
+ std::mutex shutdown_command_lock_;
+ std::string shutdown_command_;
+ bool do_shutdown_ = false;
+} shutdown_state;
+
void DumpState() {
ServiceList::GetInstance().DumpState();
ActionManager::GetInstance().DumpState();
@@ -156,39 +299,7 @@
}
}
-bool start_waiting_for_property(const char* name, const char* value) {
- if (waiting_for_prop) {
- return false;
- }
- if (GetProperty(name, "") != value) {
- // Current property value is not equal to expected value
- wait_prop_name = name;
- wait_prop_value = value;
- waiting_for_prop.reset(new Timer());
- } else {
- LOG(INFO) << "start_waiting_for_property(\"" << name << "\", \"" << value
- << "\"): already set";
- }
- return true;
-}
-
-void ResetWaitForProp() {
- wait_prop_name.clear();
- wait_prop_value.clear();
- waiting_for_prop.reset();
-}
-
-static void TriggerShutdown(const std::string& command) {
- // We can't call HandlePowerctlMessage() directly in this function,
- // because it modifies the contents of the action queue, which can cause the action queue
- // to get into a bad state if this function is called from a command being executed by the
- // action queue. Instead we set this flag and ensure that shutdown happens before the next
- // command is run in the main init loop.
- shutdown_command = command;
- do_shutdown = true;
-}
-
-void property_changed(const std::string& name, const std::string& value) {
+void PropertyChanged(const std::string& name, const std::string& value) {
// If the property is sys.powerctl, we bypass the event queue and immediately handle it.
// This is to ensure that init will always and immediately shutdown/reboot, regardless of
// if there are other pending events to process or if init is waiting on an exec service or
@@ -196,26 +307,15 @@
// In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific
// commands to be executed.
if (name == "sys.powerctl") {
- TriggerShutdown(value);
+ trigger_shutdown(value);
}
- if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value);
-
- // We always record how long init waited for ueventd to tell us cold boot finished.
- // If we aren't waiting on this property, it means that ueventd finished before we even started
- // to wait.
- if (name == kColdBootDoneProp) {
- auto time_waited = waiting_for_prop ? waiting_for_prop->duration().count() : 0;
- SetProperty("ro.boottime.init.cold_boot_wait", std::to_string(time_waited));
+ if (property_triggers_enabled) {
+ ActionManager::GetInstance().QueuePropertyChange(name, value);
+ WakeEpoll();
}
- if (waiting_for_prop) {
- if (wait_prop_name == name && wait_prop_value == value) {
- LOG(INFO) << "Wait for property '" << wait_prop_name << "=" << wait_prop_value
- << "' took " << *waiting_for_prop;
- ResetWaitForProp();
- }
- }
+ prop_waiter_state.CheckAndResetWait(name, value);
}
static std::optional<boot_clock::time_point> HandleProcessActions() {
@@ -343,8 +443,46 @@
return true;
}
+bool QueueControlMessage(const std::string& message, const std::string& name, pid_t pid, int fd) {
+ auto lock = std::lock_guard{pending_control_messages_lock};
+ if (pending_control_messages.size() > 100) {
+ LOG(ERROR) << "Too many pending control messages, dropped '" << message << "' for '" << name
+ << "' from pid: " << pid;
+ return false;
+ }
+ pending_control_messages.push({message, name, pid, fd});
+ WakeEpoll();
+ return true;
+}
+
+static void HandleControlMessages() {
+ auto lock = std::unique_lock{pending_control_messages_lock};
+ // Init historically would only execute handle one property message, including control messages
+ // in each iteration of its main loop. We retain this behavior here to prevent starvation of
+ // other actions in the main loop.
+ if (!pending_control_messages.empty()) {
+ auto control_message = pending_control_messages.front();
+ pending_control_messages.pop();
+ lock.unlock();
+
+ bool success = HandleControlMessage(control_message.message, control_message.name,
+ control_message.pid);
+
+ uint32_t response = success ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE;
+ if (control_message.fd != -1) {
+ TEMP_FAILURE_RETRY(send(control_message.fd, &response, sizeof(response), 0));
+ close(control_message.fd);
+ }
+ lock.lock();
+ }
+ // If we still have items to process, make sure we wake back up to do so.
+ if (!pending_control_messages.empty()) {
+ WakeEpoll();
+ }
+}
+
static Result<void> wait_for_coldboot_done_action(const BuiltinArguments& args) {
- if (!start_waiting_for_property(kColdBootDoneProp, "true")) {
+ if (!prop_waiter_state.StartWaiting(kColdBootDoneProp, "true")) {
LOG(FATAL) << "Could not wait for '" << kColdBootDoneProp << "'";
}
@@ -562,60 +700,6 @@
}
}
-void SendStopSendingMessagesMessage() {
- auto init_message = InitMessage{};
- init_message.set_stop_sending_messages(true);
- if (auto result = SendMessage(property_fd, init_message); !result.ok()) {
- LOG(ERROR) << "Failed to send 'stop sending messages' message: " << result.error();
- }
-}
-
-void SendStartSendingMessagesMessage() {
- auto init_message = InitMessage{};
- init_message.set_start_sending_messages(true);
- if (auto result = SendMessage(property_fd, init_message); !result.ok()) {
- LOG(ERROR) << "Failed to send 'start sending messages' message: " << result.error();
- }
-}
-
-static void HandlePropertyFd() {
- auto message = ReadMessage(property_fd);
- if (!message.ok()) {
- LOG(ERROR) << "Could not read message from property service: " << message.error();
- return;
- }
-
- auto property_message = PropertyMessage{};
- if (!property_message.ParseFromString(*message)) {
- LOG(ERROR) << "Could not parse message from property service";
- return;
- }
-
- switch (property_message.msg_case()) {
- case PropertyMessage::kControlMessage: {
- auto& control_message = property_message.control_message();
- bool success = HandleControlMessage(control_message.msg(), control_message.name(),
- control_message.pid());
-
- uint32_t response = success ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE;
- if (control_message.has_fd()) {
- int fd = control_message.fd();
- TEMP_FAILURE_RETRY(send(fd, &response, sizeof(response), 0));
- close(fd);
- }
- break;
- }
- case PropertyMessage::kChangedMessage: {
- auto& changed_message = property_message.changed_message();
- property_changed(changed_message.name(), changed_message.value());
- break;
- }
- default:
- LOG(ERROR) << "Unknown message type from property service: "
- << property_message.msg_case();
- }
-}
-
int SecondStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
@@ -623,7 +707,7 @@
boot_clock::time_point start_time = boot_clock::now();
- trigger_shutdown = TriggerShutdown;
+ trigger_shutdown = [](const std::string& command) { shutdown_state.TriggerShutdown(command); };
SetStdioToDevNull(argv);
InitKernelLogging(argv);
@@ -683,11 +767,8 @@
}
InstallSignalFdHandler(&epoll);
-
+ InstallInitNotifier(&epoll);
StartPropertyService(&property_fd);
- if (auto result = epoll.RegisterHandler(property_fd, HandlePropertyFd); !result.ok()) {
- LOG(FATAL) << "Could not register epoll handler for property fd: " << result.error();
- }
// Make the time that init stages started available for bootstat to log.
RecordStageBoottimes(start_time);
@@ -770,12 +851,12 @@
// By default, sleep until something happens.
auto epoll_timeout = std::optional<std::chrono::milliseconds>{};
- if (do_shutdown && !IsShuttingDown()) {
- do_shutdown = false;
- HandlePowerctlMessage(shutdown_command);
+ auto shutdown_command = shutdown_state.CheckShutdown();
+ if (shutdown_command) {
+ HandlePowerctlMessage(*shutdown_command);
}
- if (!(waiting_for_prop || Service::is_exec_service_running())) {
+ if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) {
am.ExecuteOneCommand();
}
if (!IsShuttingDown()) {
@@ -789,7 +870,7 @@
}
}
- if (!(waiting_for_prop || Service::is_exec_service_running())) {
+ if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) {
// If there's more work to do, wake up again immediately.
if (am.HasMoreCommands()) epoll_timeout = 0ms;
}
@@ -806,6 +887,7 @@
(*function)();
}
}
+ HandleControlMessages();
}
return 0;
diff --git a/init/init.h b/init/init.h
index 4bbca6f..27f64e2 100644
--- a/init/init.h
+++ b/init/init.h
@@ -38,8 +38,9 @@
void ResetWaitForProp();
void SendLoadPersistentPropertiesMessage();
-void SendStopSendingMessagesMessage();
-void SendStartSendingMessagesMessage();
+
+void PropertyChanged(const std::string& name, const std::string& value);
+bool QueueControlMessage(const std::string& message, const std::string& name, pid_t pid, int fd);
int SecondStageMain(int argc, char** argv);
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 730bf6d..8206522 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -92,8 +92,11 @@
static bool persistent_properties_loaded = false;
static int property_set_fd = -1;
+static int from_init_socket = -1;
static int init_socket = -1;
static bool accept_messages = false;
+static std::mutex accept_messages_lock;
+static std::thread property_service_thread;
static PropertyInfoAreaFile property_info_area;
@@ -115,6 +118,16 @@
return 0;
}
+void StartSendingMessages() {
+ auto lock = std::lock_guard{accept_messages_lock};
+ accept_messages = true;
+}
+
+void StopSendingMessages() {
+ auto lock = std::lock_guard{accept_messages_lock};
+ accept_messages = true;
+}
+
bool CanReadProperty(const std::string& source_context, const std::string& name) {
const char* target_context = nullptr;
property_info_area->GetPropertyInfo(name.c_str(), &target_context, nullptr);
@@ -147,17 +160,6 @@
return has_access;
}
-static void SendPropertyChanged(const std::string& name, const std::string& value) {
- auto property_msg = PropertyMessage{};
- auto* changed_message = property_msg.mutable_changed_message();
- changed_message->set_name(name);
- changed_message->set_value(value);
-
- if (auto result = SendMessage(init_socket, property_msg); !result.ok()) {
- LOG(ERROR) << "Failed to send property changed message: " << result.error();
- }
-}
-
static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {
size_t valuelen = value.size();
@@ -195,8 +197,9 @@
}
// If init hasn't started its main loop, then it won't be handling property changed messages
// anyway, so there's no need to try to send them.
+ auto lock = std::lock_guard{accept_messages_lock};
if (accept_messages) {
- SendPropertyChanged(name, value);
+ PropertyChanged(name, value);
}
return PROP_SUCCESS;
}
@@ -373,33 +376,24 @@
static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid,
SocketConnection* socket, std::string* error) {
+ auto lock = std::lock_guard{accept_messages_lock};
if (!accept_messages) {
*error = "Received control message after shutdown, ignoring";
return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
}
- auto property_msg = PropertyMessage{};
- auto* control_message = property_msg.mutable_control_message();
- control_message->set_msg(msg);
- control_message->set_name(name);
- control_message->set_pid(pid);
-
// We must release the fd before sending it to init, otherwise there will be a race with init.
// If init calls close() before Release(), then fdsan will see the wrong tag and abort().
int fd = -1;
if (socket != nullptr && SelinuxGetVendorAndroidVersion() > __ANDROID_API_Q__) {
fd = socket->Release();
- control_message->set_fd(fd);
}
- if (auto result = SendMessage(init_socket, property_msg); !result.ok()) {
- // We've already released the fd above, so if we fail to send the message to init, we need
- // to manually free it here.
- if (fd != -1) {
- close(fd);
- }
- *error = "Failed to send control message: " + result.error().message();
- return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
+ bool queue_success = QueueControlMessage(msg, name, pid, fd);
+ if (!queue_success && fd != -1) {
+ uint32_t response = PROP_ERROR_HANDLE_CONTROL_MESSAGE;
+ TEMP_FAILURE_RETRY(send(fd, &response, sizeof(response), 0));
+ close(fd);
}
return PROP_SUCCESS;
@@ -1110,14 +1104,6 @@
persistent_properties_loaded = true;
break;
}
- case InitMessage::kStopSendingMessages: {
- accept_messages = false;
- break;
- }
- case InitMessage::kStartSendingMessages: {
- accept_messages = true;
- break;
- }
default:
LOG(ERROR) << "Unknown message type from init: " << init_message.msg_case();
}
@@ -1157,9 +1143,9 @@
if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sockets) != 0) {
PLOG(FATAL) << "Failed to socketpair() between property_service and init";
}
- *epoll_socket = sockets[0];
+ *epoll_socket = from_init_socket = sockets[0];
init_socket = sockets[1];
- accept_messages = true;
+ StartSendingMessages();
if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
false, 0666, 0, 0, {});
@@ -1171,7 +1157,8 @@
listen(property_set_fd, 8);
- std::thread{PropertyServiceThread}.detach();
+ auto new_thread = std::thread{PropertyServiceThread};
+ property_service_thread.swap(new_thread);
}
} // namespace init
diff --git a/init/property_service.h b/init/property_service.h
index 506d116..2d49a36 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -32,5 +32,8 @@
void PropertyInit();
void StartPropertyService(int* epoll_socket);
+void StartSendingMessages();
+void StopSendingMessages();
+
} // namespace init
} // namespace android
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 8d8bd8e..f006df3 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -59,6 +59,7 @@
#include "builtin_arguments.h"
#include "init.h"
#include "mount_namespace.h"
+#include "property_service.h"
#include "reboot_utils.h"
#include "service.h"
#include "service_list.h"
@@ -711,17 +712,12 @@
for (const auto& s : ServiceList::GetInstance()) {
s->UnSetExec();
}
- // We no longer process messages about properties changing coming from property service, so we
- // need to tell property service to stop sending us these messages, otherwise it'll fill the
- // buffers and block indefinitely, causing future property sets, including those that init makes
- // during shutdown in Service::NotifyStateChange() to also block indefinitely.
- SendStopSendingMessagesMessage();
}
static void LeaveShutdown() {
LOG(INFO) << "Leaving shutdown mode";
shutting_down = false;
- SendStartSendingMessagesMessage();
+ StartSendingMessages();
}
static Result<void> UnmountAllApexes() {
@@ -981,6 +977,10 @@
return;
}
+ // We do not want to process any messages (queue'ing triggers, shutdown messages, control
+ // messages, etc) from properties during reboot.
+ StopSendingMessages();
+
if (userspace_reboot) {
HandleUserspaceReboot();
return;
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 57531c8..76caadc 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -97,6 +97,9 @@
},
android: {
static_libs: ["libasync_safe"],
+ static: {
+ whole_static_libs: ["libasync_safe"],
+ },
},
vendor: {
cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index c4e4f85..5805a4d 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -201,6 +201,8 @@
CAP_MASK_LONG(CAP_SETGID),
"system/bin/simpleperf_app_runner" },
{ 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/e2fsck" },
+ { 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/tune2fs" },
+ { 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/resize2fs" },
// generic defaults
{ 00755, AID_ROOT, AID_ROOT, 0, "bin/*" },
{ 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" },
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 50faa2a..0b98e1a 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -121,8 +121,12 @@
logtags: ["event.logtags"],
compile_multilib: "both",
apex_available: [
- "//apex_available:anyapex",
"//apex_available:platform",
+ // liblog is exceptionally available to the runtime APEX
+ // because the dynamic linker has to use it statically.
+ // See b/151051671
+ "com.android.runtime",
+ // DO NOT add more apex names here
],
}
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index 15c7963..43a91ab 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -56,6 +56,7 @@
#include <stdarg.h>
#include <stddef.h>
+#include <stdint.h>
#include <sys/cdefs.h>
#if !defined(__BIONIC__) && !defined(__INTRODUCED_IN)
@@ -154,14 +155,11 @@
/** The kernel log buffer. */
LOG_ID_KERNEL = 7,
- LOG_ID_MAX
-} log_id_t;
+ LOG_ID_MAX,
-/**
- * Let the logging function choose the best log target.
- * This is not part of the enum since adding either -1 or 0xFFFFFFFF forces the enum to be signed or
- * unsigned, which breaks unfortunately common arithmetic against LOG_ID_MIN and LOG_ID_MAX. */
-#define LOG_ID_DEFAULT (-1)
+ /** Let the logging function choose the best log target. */
+ LOG_ID_DEFAULT = 0x7FFFFFFF
+} log_id_t;
/**
* Writes the constant string `text` to the log buffer `id`,
@@ -188,11 +186,11 @@
*/
struct __android_logger_data {
size_t struct_size; /* Must be set to sizeof(__android_logger_data) and is used for versioning. */
- int buffer_id; /* log_id_t or -1 to represent 'default'. */
- int priority; /* android_LogPriority values. */
+ int32_t buffer_id; /* log_id_t or -1 to represent 'default'. */
+ int32_t priority; /* android_LogPriority values. */
const char* tag;
const char* file; /* Optional file name, may be set to nullptr. */
- unsigned int line; /* Optional line number, ignore if file is nullptr. */
+ uint32_t line; /* Optional line number, ignore if file is nullptr. */
};
/**
@@ -206,7 +204,7 @@
*/
typedef void (*__android_aborter_function)(const char* abort_message);
-#if __ANDROID_API__ >= 30 || !defined(__ANDROID__)
+#if !defined(__ANDROID__) || __ANDROID_API__ >= 30
/**
* Writes the log message specified with logger_data and msg to the log. logger_data includes
* additional file name and line number information that a logger may use. logger_data is versioned
@@ -276,13 +274,13 @@
*
* This returns the previous set minimum priority, or ANDROID_LOG_DEFAULT if none was set.
*/
-int __android_log_set_minimum_priority(int priority) __INTRODUCED_IN(30);
+int32_t __android_log_set_minimum_priority(int32_t priority) __INTRODUCED_IN(30);
/**
* Gets the minimum priority that will be logged for this process. If none has been set by a
* previous __android_log_set_minimum_priority() call, this returns ANDROID_LOG_DEFAULT.
*/
-int __android_log_get_minimum_priority(void) __INTRODUCED_IN(30);
+int32_t __android_log_get_minimum_priority(void) __INTRODUCED_IN(30);
/**
* Sets the default tag if no tag is provided when writing a log message. Defaults to
diff --git a/liblog/logger_name.cpp b/liblog/logger_name.cpp
index 7d676f4..e72290e 100644
--- a/liblog/logger_name.cpp
+++ b/liblog/logger_name.cpp
@@ -41,7 +41,10 @@
}
static_assert(std::is_same<std::underlying_type<log_id_t>::type, uint32_t>::value,
- "log_id_t must be an unsigned int");
+ "log_id_t must be an uint32_t");
+
+static_assert(std::is_same<std::underlying_type<android_LogPriority>::type, uint32_t>::value,
+ "log_id_t must be an uint32_t");
log_id_t android_name_to_log_id(const char* logName) {
const char* b;
diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp
index 0dbb94f..a8620a0 100644
--- a/liblog/logger_write.cpp
+++ b/liblog/logger_write.cpp
@@ -149,12 +149,12 @@
GetDefaultTag().assign(tag, 0, LOGGER_ENTRY_MAX_PAYLOAD);
}
-static std::atomic_int minimum_log_priority = ANDROID_LOG_DEFAULT;
-int __android_log_set_minimum_priority(int priority) {
+static std::atomic_int32_t minimum_log_priority = ANDROID_LOG_DEFAULT;
+int32_t __android_log_set_minimum_priority(int32_t priority) {
return minimum_log_priority.exchange(priority, std::memory_order_relaxed);
}
-int __android_log_get_minimum_priority() {
+int32_t __android_log_get_minimum_priority() {
return minimum_log_priority;
}
@@ -267,7 +267,7 @@
static const char log_characters[] = "XXVDIWEF";
static_assert(arraysize(log_characters) - 1 == ANDROID_LOG_SILENT,
"Mismatch in size of log_characters and values in android_LogPriority");
- int priority =
+ int32_t priority =
logger_data->priority > ANDROID_LOG_SILENT ? ANDROID_LOG_FATAL : logger_data->priority;
char priority_char = log_characters[priority];
uint64_t tid = GetThreadId();
diff --git a/libpixelflinger/Android.bp b/libpixelflinger/Android.bp
index 76d9444..45a32da 100644
--- a/libpixelflinger/Android.bp
+++ b/libpixelflinger/Android.bp
@@ -93,23 +93,5 @@
"arch-arm64/t32cb16blend.S",
],
},
- mips: {
- mips32r6: {
- srcs: [
- "codeflinger/MIPSAssembler.cpp",
- "codeflinger/mips_disassem.c",
- "arch-mips/t32cb16blend.S",
- ],
- },
- },
- mips64: {
- srcs: [
- "codeflinger/MIPSAssembler.cpp",
- "codeflinger/MIPS64Assembler.cpp",
- "codeflinger/mips64_disassem.c",
- "arch-mips64/col32cb16blend.S",
- "arch-mips64/t32cb16blend.S",
- ],
- },
},
}
diff --git a/libpixelflinger/arch-mips/col32cb16blend.S b/libpixelflinger/arch-mips/col32cb16blend.S
deleted file mode 100644
index 810294c..0000000
--- a/libpixelflinger/arch-mips/col32cb16blend.S
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-** Copyright 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
- .macro pixel dreg src f sR sG sB shift
-
-#if __mips==32 && __mips_isa_rev>=2
- /* extract red */
- ext $t4,\src,\shift+11,5
- mul $t4,$t4,\f
-
- /* extract green */
- ext $t5,\src,\shift+5,6
- mul $t5,$t5,\f
-
- /* extract blue */
- ext $t6,\src,\shift,5
- mul $t6,$t6,\f
-#else
- /* extract red */
- srl $t4,\src,\shift+11
- andi $t4, 0x1f
- mul $t4,$t4,\f
-
- /* extract green */
- srl $t5,\src,\shift+5
- andi $t5, 0x3f
- mul $t5,$t5,\f
-
- /* extract blue */
- srl $t6,\src,\shift
- andi $t6, 0x1f
- mul $t6,$t6,\f
-#endif
-
- srl $t4,$t4,8
- srl $t5,$t5,8
- srl $t6,$t6,8
- addu $t4,$t4,\sR
- addu $t5,$t5,\sG
- addu \dreg,$t6,\sB
- sll $t4,$t4,11
- sll $t5,$t5,5
- or \dreg,\dreg,$t4
- or \dreg,\dreg,$t5
- andi \dreg, 0xffff
- .endm
-
- .text
- .balign 4
-
- .global scanline_col32cb16blend_mips
- .ent scanline_col32cb16blend_mips
-scanline_col32cb16blend_mips:
-
- /* check if count is zero */
- srl $v0,$a1,24 /* sA */
- beqz $a2,done
- li $t4, 0x100
- srl $v1,$v0,7
- addu $v0,$v1,$v0
- subu $v0,$t4,$v0 /* f */
-#if __mips==32 && __mips_isa_rev>=2
- ext $a3,$a1,3,5 /* sR */
- ext $t0,$a1,10,6 /* sG */
- ext $t1,$a1,19,5 /* sB */
-#else
- srl $a3, $a1, 3
- andi $a3, 0x1f /* sR */
- srl $t0, $a1, 10
- andi $t0, 0x3f /* sG */
- srl $t1, $a1, 19
- andi $t1, 0x1f /* sB */
-#endif
-
- /* check if cnt is at least 4 */
- addiu $a2,$a2,-4
- bltz $a2,tail
-
-loop_4pixels:
- lw $t7,0($a0)
- lw $t8,4($a0)
- addiu $a0,$a0,8
- addiu $a2,$a2,-4
- pixel $t2 $t7 $v0 $a3 $t0 $t1 0
- pixel $t3 $t7 $v0 $a3 $t0 $t1 16
-#if __mips==32 && __mips_isa_rev>=2
- ins $t2,$t3,16,16
-#else
- sll $t3, 16
- or $t2, $t2, $t3
-#endif
- pixel $t7 $t8 $v0 $a3 $t0 $t1 0
- pixel $t3 $t8 $v0 $a3 $t0 $t1 16
-#if __mips==32 && __mips_isa_rev>=2
- ins $t7,$t3,16,16
-#else
- sll $t3, 16
- or $t7, $t7, $t3
-#endif
- sw $t2,-8($a0)
- sw $t7,-4($a0)
- bgez $a2, loop_4pixels
-
-tail:
- /* the pixel count underran, restore it now */
- addiu $a2,$a2,4
-
- /* handle the last 0..3 pixels */
- beqz $a2,done
-
-loop_1pixel:
- lhu $t7,0($a0)
- addiu $a0,$a0,2
- addiu $a2,$a2,-1
- pixel $t2 $t7 $v0 $a3 $t0 $t1 0
- sh $t2, -2($a0)
- bnez $a2,loop_1pixel
-
-done:
- j $ra
- .end scanline_col32cb16blend_mips
diff --git a/libpixelflinger/arch-mips/t32cb16blend.S b/libpixelflinger/arch-mips/t32cb16blend.S
deleted file mode 100644
index 1d2fb8f..0000000
--- a/libpixelflinger/arch-mips/t32cb16blend.S
+++ /dev/null
@@ -1,273 +0,0 @@
-/* libs/pixelflinger/t32cb16blend.S
-**
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifdef DEBUG
-#define DBG
-#else
-#define DBG #
-#endif
-
-/*
- * blend one of 2 16bpp RGB pixels held in dreg selected by shift
- * with the 32bpp ABGR pixel held in src and store the result in fb
- *
- * Assumes that the dreg data is little endian and that
- * the the second pixel (shift==16) will be merged into
- * the fb result
- *
- * Uses $t0,$t6,$t7,$t8
- */
-
-#if __mips==32 && __mips_isa_rev>=2
- .macro pixel dreg src fb shift
- /*
- * sA = s >> 24
- * f = 0x100 - (sA + (sA>>7))
- */
-DBG .set noat
-DBG rdhwr $at,$2
-DBG .set at
-
- srl $t7,\src,24
- srl $t6,$t7,7
- addu $t7,$t6
- li $t6,0x100
- subu $t7,$t6,$t7
-
- /* red */
- ext $t8,\dreg,\shift+6+5,5 # dst[\shift:15..11]
- mul $t6,$t8,$t7
- ext $t0,\dreg,\shift+5,6 # start green extraction dst[\shift:10..5]
- ext $t8,\src,3,5 # src[7..3]
- srl $t6,8
- addu $t8,$t6
-.if \shift!=0
- sll $t8,\shift+11
- or \fb,$t8
-.else
- sll \fb,$t8,11
-.endif
-
- /* green */
- mul $t8,$t0,$t7
- ext $t0,\dreg,\shift,5 # start blue extraction dst[\shift:4..0]
- ext $t6,\src,2+8,6 # src[15..10]
- srl $t8,8
- addu $t8,$t6
-
- /* blue */
- mul $t0,$t0,$t7
- sll $t8, $t8, \shift+5
- or \fb, \fb, $t8
- ext $t6,\src,(3+8+8),5
- srl $t8,$t0,8
- addu $t8,$t6
- sll $t8, $t8, \shift
- or \fb, \fb, $t8
-
-DBG .set noat
-DBG rdhwr $t8,$2
-DBG subu $t8,$at
-DBG sltu $at,$t8,$v0
-DBG movn $v0,$t8,$at
-DBG sgtu $at,$t8,$v1
-DBG movn $v1,$t8,$at
-DBG .set at
- .endm
-
-#else
-
- .macro pixel dreg src fb shift
- /*
- * sA = s >> 24
- * f = 0x100 - (sA + (sA>>7))
- */
-DBG .set push
-DBG .set noat
-DBG .set mips32r2
-DBG rdhwr $at,$2
-DBG .set pop
-
- srl $t7,\src,24
- srl $t6,$t7,7
- addu $t7,$t6
- li $t6,0x100
- subu $t7,$t6,$t7
-
- /*
- * red
- * dR = (d >> (6 + 5)) & 0x1f;
- * dR = (f*dR)>>8
- * sR = (s >> ( 3)) & 0x1f;
- * sR += dR
- * fb |= sR << 11
- */
- srl $t8,\dreg,\shift+6+5
-.if \shift==0
- and $t8,0x1f
-.endif
- mul $t8,$t8,$t7
- srl $t6,\src,3
- and $t6,0x1f
- srl $t8,8
- addu $t8,$t6
-.if \shift!=0
- sll $t8,\shift+11
- or \fb,$t8
-.else
- sll \fb,$t8,11
-.endif
-
- /*
- * green
- * dG = (d >> 5) & 0x3f
- * dG = (f*dG) >> 8
- * sG = (s >> ( 8+2))&0x3F;
- */
- srl $t8,\dreg,\shift+5
- and $t8,0x3f
- mul $t8,$t8,$t7
- srl $t6,\src,8+2
- and $t6,0x3f
- srl $t8,8
- addu $t8,$t6
- sll $t8,\shift + 5
- or \fb,$t8
-
- /* blue */
-.if \shift!=0
- srl $t8,\dreg,\shift
- and $t8,0x1f
-.else
- and $t8,\dreg,0x1f
-.endif
- mul $t8,$t8,$t7
- srl $t6,\src,(8+8+3)
- and $t6,0x1f
- srl $t8,8
- addu $t8,$t6
-.if \shift!=0
- sll $t8,\shift
-.endif
- or \fb,$t8
-DBG .set push
-DBG .set noat
-DBG .set mips32r2
-DBG rdhwr $t8,$2
-DBG subu $t8,$at
-DBG sltu $at,$t8,$v0
-DBG movn $v0,$t8,$at
-DBG sgtu $at,$t8,$v1
-DBG movn $v1,$t8,$at
-DBG .set pop
- .endm
-#endif
-
- .text
- .balign 4
-
- .global scanline_t32cb16blend_mips
- .ent scanline_t32cb16blend_mips
-scanline_t32cb16blend_mips:
-DBG li $v0,0xffffffff
-DBG li $v1,0
- /* Align the destination if necessary */
- and $t0,$a0,3
- beqz $t0,aligned
-
- /* as long as there is at least one pixel */
- beqz $a2,done
-
- lw $t4,($a1)
- addu $a0,2
- addu $a1,4
- beqz $t4,1f
- lhu $t3,-2($a0)
- pixel $t3,$t4,$t1,0
- sh $t1,-2($a0)
-1: subu $a2,1
-
-aligned:
- /* Check to see if its worth unrolling the loop */
- subu $a2,4
- bltz $a2,tail
-
- /* Process 4 pixels at a time */
-fourpixels:
- /* 1st pair of pixels */
- lw $t4,0($a1)
- lw $t5,4($a1)
- addu $a0,8
- addu $a1,16
-
- /* both are zero, skip this pair */
- or $t3,$t4,$t5
- beqz $t3,1f
-
- /* load the destination */
- lw $t3,-8($a0)
-
- pixel $t3,$t4,$t1,0
- andi $t1, 0xFFFF
- pixel $t3,$t5,$t1,16
- sw $t1,-8($a0)
-
-1:
- /* 2nd pair of pixels */
- lw $t4,-8($a1)
- lw $t5,-4($a1)
-
- /* both are zero, skip this pair */
- or $t3,$t4,$t5
- beqz $t3,1f
-
- /* load the destination */
- lw $t3,-4($a0)
-
- pixel $t3,$t4,$t1,0
- andi $t1, 0xFFFF
- pixel $t3,$t5,$t1,16
- sw $t1,-4($a0)
-
-1: subu $a2,4
- bgtz $a2,fourpixels
-
-tail:
- /* the pixel count underran, restore it now */
- addu $a2,4
-
- /* handle the last 0..3 pixels */
- beqz $a2,done
-onepixel:
- lw $t4,($a1)
- addu $a0,2
- addu $a1,4
- beqz $t4,1f
- lhu $t3,-2($a0)
- pixel $t3,$t4,$t1,0
- sh $t1,-2($a0)
-1: subu $a2,1
- bnez $a2,onepixel
-done:
-DBG .set push
-DBG .set mips32r2
-DBG rdhwr $a0,$3
-DBG mul $v0,$a0
-DBG mul $v1,$a0
-DBG .set pop
- j $ra
- .end scanline_t32cb16blend_mips
diff --git a/libpixelflinger/arch-mips64/col32cb16blend.S b/libpixelflinger/arch-mips64/col32cb16blend.S
deleted file mode 100644
index 5baffb1..0000000
--- a/libpixelflinger/arch-mips64/col32cb16blend.S
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
-** Copyright 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
- .macro pixel dreg src f sR sG sB shift
-
- /* extract red */
-.if \shift < 32
- dext $t0,\src,\shift+11,5
-.else
- dextu $t0,\src,\shift+11,5
-.endif
- mul $t0,$t0,\f
-
- /* extract green */
-.if \shift < 32
- dext $t1,\src,\shift+5,6
-.else
- dextu $t1,\src,\shift+5,6
-.endif
- mul $t1,$t1,\f
-
- /* extract blue */
-.if \shift < 32
- dext $t2,\src,\shift,5
-.else
- dextu $t2,\src,\shift,5
-.endif
- mul $t2,$t2,\f
-
- srl $t0,$t0,8
- srl $t1,$t1,8
- srl $t2,$t2,8
- addu $t0,$t0,\sR
- addu $t1,$t1,\sG
- addu \dreg,$t2,\sB
- sll $t0,$t0,11
- sll $t1,$t1,5
- or \dreg,\dreg,$t0
- or \dreg,\dreg,$t1
- .endm
-
- .text
- .balign 4
-
- .global scanline_col32cb16blend_mips64
- .ent scanline_col32cb16blend_mips64
-scanline_col32cb16blend_mips64:
-
- /* check if count is zero */
- srl $v0,$a1,24 /* sA */
- beqz $a2,done
- li $t0, 0x100
- srl $v1,$v0,7
- addu $v0,$v1,$v0
- subu $v0,$t0,$v0 /* f */
- ext $a3,$a1,3,5 /* sR */
- ext $a4,$a1,10,6 /* sG */
- ext $a5,$a1,19,5 /* sB */
-
- /* check if cnt is at least 4 */
- addiu $a2,$a2,-4
- bltz $a2,tail
-
-loop_4pixels:
- ld $t3,0($a0)
- daddiu $a0,$a0,8
- addiu $a2,$a2,-4
- pixel $a6 $t3 $v0 $a3 $a4 $a5 0
- pixel $a7 $t3 $v0 $a3 $a4 $a5 16
- pixel $t8 $t3 $v0 $a3 $a4 $a5 32
- pixel $t9 $t3 $v0 $a3 $a4 $a5 48
- dins $a6,$a7,16,16
- dinsu $a6,$t8,32,16
- dinsu $a6,$t9,48,16
- sd $a6,-8($a0)
- bgez $a2, loop_4pixels
-
-tail:
- /* the pixel count underran, restore it now */
- addiu $a2,$a2,4
-
- /* handle the last 0..3 pixels */
- beqz $a2,done
-
-loop_1pixel:
- lhu $t3,0($a0)
- daddiu $a0,$a0,2
- addiu $a2,$a2,-1
- pixel $a6 $t3 $v0 $a3 $a4 $a5 0
- sh $a6, -2($a0)
- bnez $a2,loop_1pixel
-
-done:
- j $ra
- .end scanline_col32cb16blend_mips64
diff --git a/libpixelflinger/arch-mips64/t32cb16blend.S b/libpixelflinger/arch-mips64/t32cb16blend.S
deleted file mode 100644
index 3cb5f93..0000000
--- a/libpixelflinger/arch-mips64/t32cb16blend.S
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
-** Copyright 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifdef DEBUG
-#define DBG
-#else
-#define DBG #
-#endif
-
-/*
- * blend one of 2 16bpp RGB pixels held in dreg selected by shift
- * with the 32bpp ABGR pixel held in src and store the result in fb
- *
- * Assumes that the dreg data is little endian and that
- * the the second pixel (shift==16) will be merged into
- * the fb result
- *
- * Uses $a4,$t2,$t3,$t8
- */
-
- .macro pixel dreg src fb shift
- /*
- * sA = s >> 24
- * f = 0x100 - (sA + (sA>>7))
- */
- srl $t3,\src,24
- srl $t2,$t3,7
- addu $t3,$t2
- li $t2,0x100
- subu $t3,$t2,$t3
-
- /* red */
- ext $t8,\dreg,\shift+6+5,5 # dst[\shift:15..11]
- mul $t2,$t8,$t3
- ext $a4,\dreg,\shift+5,6 # start green extraction dst[\shift:10..5]
- ext $t8,\src,3,5 # src[7..3]
- srl $t2,8
- addu $t8,$t2
-.if \shift!=0
- sll $t8,\shift+11 # dst[\shift:15..11]
- or \fb,$t8
-.else
- sll \fb,$t8,11
-.endif
-
- /* green */
- mul $t8,$a4,$t3
- ext $a4,\dreg,\shift,5 # start blue extraction dst[\shift:4..0]
- ext $t2,\src,2+8,6 # src[15..10]
- srl $t8,8
- addu $t8,$t2
-
- /* blue */
- mul $a4,$a4,$t3
- sll $t8, $t8, \shift+5 # finish green insertion dst[\shift:10..5]
- or \fb, \fb, $t8
- ext $t2,\src,(3+8+8),5
- srl $t8,$a4,8
- addu $t8,$t2
- sll $t8, $t8, \shift
- or \fb, \fb, $t8
- .endm
-
- .text
- .balign 4
-
- .global scanline_t32cb16blend_mips64
- .ent scanline_t32cb16blend_mips64
-scanline_t32cb16blend_mips64:
- daddiu $sp, $sp, -40
-DBG li $v0,0xffffffff
-DBG li $v1,0
- /* Align the destination if necessary */
- and $a4,$a0,3
- beqz $a4,aligned
-
- /* as long as there is at least one pixel */
- beqz $a2,done
-
- lw $t0,($a1)
- daddu $a0,2
- daddu $a1,4
- beqz $t0,1f
- lhu $a7,-2($a0)
- pixel $a7,$t0,$a5,0
- sh $a5,-2($a0)
-1: subu $a2,1
-
-aligned:
- /* Check to see if its worth unrolling the loop */
- subu $a2,4
- bltz $a2,tail
-
- /* Process 4 pixels at a time */
-fourpixels:
- /* 1st pair of pixels */
- lw $t0,0($a1)
- lw $t1,4($a1)
- daddu $a0,8
- daddu $a1,16
-
- /* both are zero, skip this pair */
- or $a7,$t0,$t1
- beqz $a7,1f
-
- /* load the destination */
- lw $a7,-8($a0)
-
- pixel $a7,$t0,$a5,0
- andi $a5, 0xFFFF
- pixel $a7,$t1,$a5,16
- sw $a5,-8($a0)
-
-1:
- /* 2nd pair of pixels */
- lw $t0,-8($a1)
- lw $t1,-4($a1)
-
- /* both are zero, skip this pair */
- or $a7,$t0,$t1
- beqz $a7,1f
-
- /* load the destination */
- lw $a7,-4($a0)
-
- pixel $a7,$t0,$a5,0
- andi $a5, 0xFFFF
- pixel $a7,$t1,$a5,16
- sw $a5,-4($a0)
-
-1: subu $a2,4
- bgtz $a2,fourpixels
-
-tail:
- /* the pixel count underran, restore it now */
- addu $a2,4
-
- /* handle the last 0..3 pixels */
- beqz $a2,done
-onepixel:
- lw $t0,($a1)
- daddu $a0,2
- daddu $a1,4
- beqz $t0,1f
- lhu $a7,-2($a0)
- pixel $a7,$t0,$a5,0
- sh $a5,-2($a0)
-1: subu $a2,1
- bnez $a2,onepixel
-done:
-DBG .set push
-DBG .set mips32r2
-DBG rdhwr $a0,$3
-DBG mul $v0,$a0
-DBG mul $v1,$a0
-DBG .set pop
- daddiu $sp, $sp, 40
- j $ra
- .end scanline_t32cb16blend_mips64
diff --git a/libpixelflinger/tests/arch-mips/Android.bp b/libpixelflinger/tests/arch-mips/Android.bp
deleted file mode 100644
index 2ca2721..0000000
--- a/libpixelflinger/tests/arch-mips/Android.bp
+++ /dev/null
@@ -1,11 +0,0 @@
-cc_defaults {
- name: "pixelflinger-tests-mips",
- defaults: ["pixelflinger-tests"],
-
- enabled: false,
- arch: {
- mips: {
- enabled: true,
- },
- },
-}
diff --git a/libpixelflinger/tests/arch-mips/col32cb16blend/Android.bp b/libpixelflinger/tests/arch-mips/col32cb16blend/Android.bp
deleted file mode 100644
index 45bfe29..0000000
--- a/libpixelflinger/tests/arch-mips/col32cb16blend/Android.bp
+++ /dev/null
@@ -1,6 +0,0 @@
-cc_test {
- name: "test-pixelflinger-mips-col32cb16blend",
- defaults: ["pixelflinger-tests-mips"],
-
- srcs: ["col32cb16blend_test.c"],
-}
diff --git a/libpixelflinger/tests/arch-mips/col32cb16blend/col32cb16blend_test.c b/libpixelflinger/tests/arch-mips/col32cb16blend/col32cb16blend_test.c
deleted file mode 100644
index dd0e60f..0000000
--- a/libpixelflinger/tests/arch-mips/col32cb16blend/col32cb16blend_test.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
- * COPYRIGHT OWNER 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.
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-
-
-#define ARGB_8888_MAX 0xFFFFFFFF
-#define ARGB_8888_MIN 0x00000000
-#define RGB_565_MAX 0xFFFF
-#define RGB_565_MIN 0x0000
-
-struct test_t
-{
- char name[256];
- uint32_t src_color;
- uint16_t dst_color;
- size_t count;
-};
-
-struct test_t tests[] =
-{
- {"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
- {"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
- {"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
- {"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
- {"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
- {"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
- {"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
- {"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
- {"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
- {"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
-};
-
-void scanline_col32cb16blend_mips(uint16_t *dst, uint32_t src, size_t count);
-void scanline_col32cb16blend_c(uint16_t * dst, uint32_t src, size_t count)
-{
- uint32_t srcAlpha = (src>>24);
- uint32_t f = 0x100 - (srcAlpha + (srcAlpha>>7));
-
- while (count--)
- {
- uint16_t d = *dst;
- int dstR = (d>>11)&0x1f;
- int dstG = (d>>5)&0x3f;
- int dstB = (d)&0x1f;
- int srcR = (src >> ( 3))&0x1F;
- int srcG = (src >> ( 8+2))&0x3F;
- int srcB = (src >> (16+3))&0x1F;
- srcR += (f*dstR)>>8;
- srcG += (f*dstG)>>8;
- srcB += (f*dstB)>>8;
- *dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
- }
-}
-
-void scanline_col32cb16blend_test()
-{
- uint16_t dst_c[16], dst_asm[16];
- uint32_t i, j;
-
- for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
- {
- struct test_t test = tests[i];
-
- printf("Testing - %s:",test.name);
-
- memset(dst_c, 0, sizeof(dst_c));
- memset(dst_asm, 0, sizeof(dst_asm));
-
- for(j = 0; j < test.count; ++j)
- {
- dst_c[j] = test.dst_color;
- dst_asm[j] = test.dst_color;
- }
-
-
- scanline_col32cb16blend_c(dst_c, test.src_color, test.count);
- scanline_col32cb16blend_mips(dst_asm, test.src_color, test.count);
-
- if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
- printf("Passed\n");
- else
- printf("Failed\n");
-
- for(j = 0; j < test.count; ++j)
- {
- printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
- }
- }
-}
-
-int main()
-{
- scanline_col32cb16blend_test();
- return 0;
-}
diff --git a/libpixelflinger/tests/arch-mips/t32cb16blend/Android.bp b/libpixelflinger/tests/arch-mips/t32cb16blend/Android.bp
deleted file mode 100644
index 069e97c..0000000
--- a/libpixelflinger/tests/arch-mips/t32cb16blend/Android.bp
+++ /dev/null
@@ -1,6 +0,0 @@
-cc_test {
- name: "test-pixelflinger-mips-t32cb16blend",
- defaults: ["pixelflinger-tests-mips"],
-
- srcs: ["t32cb16blend_test.c"],
-}
diff --git a/libpixelflinger/tests/arch-mips/t32cb16blend/t32cb16blend_test.c b/libpixelflinger/tests/arch-mips/t32cb16blend/t32cb16blend_test.c
deleted file mode 100644
index c6d6937..0000000
--- a/libpixelflinger/tests/arch-mips/t32cb16blend/t32cb16blend_test.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
- * COPYRIGHT OWNER 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.
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-
-#define ARGB_8888_MAX 0xFFFFFFFF
-#define ARGB_8888_MIN 0x00000000
-#define RGB_565_MAX 0xFFFF
-#define RGB_565_MIN 0x0000
-
-struct test_t
-{
- char name[256];
- uint32_t src_color;
- uint16_t dst_color;
- size_t count;
-};
-
-struct test_t tests[] =
-{
- {"Count 0", 0, 0, 0},
- {"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
- {"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
- {"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
- {"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
- {"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
- {"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
- {"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
- {"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
- {"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
- {"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
-
-};
-
-void scanline_t32cb16blend_mips(uint16_t*, uint32_t*, size_t);
-void scanline_t32cb16blend_c(uint16_t * dst, uint32_t* src, size_t count)
-{
- while (count--)
- {
- uint16_t d = *dst;
- uint32_t s = *src++;
- int dstR = (d>>11)&0x1f;
- int dstG = (d>>5)&0x3f;
- int dstB = (d)&0x1f;
- int srcR = (s >> ( 3))&0x1F;
- int srcG = (s >> ( 8+2))&0x3F;
- int srcB = (s >> (16+3))&0x1F;
- int srcAlpha = (s>>24) & 0xFF;
-
-
- int f = 0x100 - (srcAlpha + ((srcAlpha>>7) & 0x1));
- srcR += (f*dstR)>>8;
- srcG += (f*dstG)>>8;
- srcB += (f*dstB)>>8;
- // srcR = srcR > 0x1F? 0x1F: srcR;
- // srcG = srcG > 0x3F? 0x3F: srcG;
- // srcB = srcB > 0x1F? 0x1F: srcB;
- *dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
- }
-}
-
-void scanline_t32cb16blend_test()
-{
- uint16_t dst_c[16], dst_asm[16];
- uint32_t src[16];
- uint32_t i;
- uint32_t j;
-
- for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
- {
- struct test_t test = tests[i];
-
- printf("Testing - %s:",test.name);
-
- memset(dst_c, 0, sizeof(dst_c));
- memset(dst_asm, 0, sizeof(dst_asm));
-
- for(j = 0; j < test.count; ++j)
- {
- dst_c[j] = test.dst_color;
- dst_asm[j] = test.dst_color;
- src[j] = test.src_color;
- }
-
- scanline_t32cb16blend_c(dst_c,src,test.count);
- scanline_t32cb16blend_mips(dst_asm,src,test.count);
-
-
- if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
- printf("Passed\n");
- else
- printf("Failed\n");
-
- for(j = 0; j < test.count; ++j)
- {
- printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
- }
- }
-}
-
-int main()
-{
- scanline_t32cb16blend_test();
- return 0;
-}
diff --git a/libpixelflinger/tests/arch-mips64/Android.bp b/libpixelflinger/tests/arch-mips64/Android.bp
deleted file mode 100644
index ba55d62..0000000
--- a/libpixelflinger/tests/arch-mips64/Android.bp
+++ /dev/null
@@ -1,11 +0,0 @@
-cc_defaults {
- name: "pixelflinger-tests-mips64",
- defaults: ["pixelflinger-tests"],
-
- enabled: false,
- arch: {
- mips64: {
- enabled: true,
- },
- },
-}
diff --git a/libpixelflinger/tests/arch-mips64/assembler/Android.bp b/libpixelflinger/tests/arch-mips64/assembler/Android.bp
deleted file mode 100644
index b672053..0000000
--- a/libpixelflinger/tests/arch-mips64/assembler/Android.bp
+++ /dev/null
@@ -1,9 +0,0 @@
-cc_test {
- name: "test-pixelflinger-mips64-assembler-test",
- defaults: ["pixelflinger-tests-mips64"],
-
- srcs: [
- "mips64_assembler_test.cpp",
- "asm_mips_test_jacket.S",
- ],
-}
diff --git a/libpixelflinger/tests/arch-mips64/assembler/asm_mips_test_jacket.S b/libpixelflinger/tests/arch-mips64/assembler/asm_mips_test_jacket.S
deleted file mode 100644
index 705ee9b..0000000
--- a/libpixelflinger/tests/arch-mips64/assembler/asm_mips_test_jacket.S
+++ /dev/null
@@ -1,93 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# * All rights reserved.
-# *
-# * Redistribution and use in source and binary forms, with or without
-# * modification, are permitted provided that the following conditions
-# * are met:
-# * * Redistributions of source code must retain the above copyright
-# * notice, this list of conditions and the following disclaimer.
-# * * 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.
-# *
-# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
-# * COPYRIGHT OWNER 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.
-# */
-
- .text
- .balign 8
-
- .global asm_mips_test_jacket
-
- # // Set the register
- # // Calls the asm function
- # // Reads the register values to output register
-
- # // Parameters
- # // a0 - Function to jump
- # // a1 - register values array
- # // a2 - flag values array
-asm_mips_test_jacket:
- # // Save registers to stack
- daddiu $sp, $sp, -96
- sd $s0, 64($sp)
- sd $s1, 72($sp)
- sd $s2, 80($sp)
- sd $ra, 88($sp)
-
- move $s0, $a0
- move $s1, $a1
- move $s2, $a2
-
- ld $v0, 16($s1)
- ld $v1, 24($s1)
- ld $a0, 32($s1)
- ld $a1, 40($s1)
- ld $a2, 48($s1)
- ld $a3, 56($s1)
- ld $a4, 64($s1)
- ld $a5, 72($s1)
- ld $a6, 80($s1)
- ld $a7, 88($s1)
- ld $t0, 96($s1)
- ld $t1, 104($s1)
- ld $t2, 112($s1)
- ld $t3, 120($s1)
-
- jal $s0
-
- sd $v0, 16($s1)
- sd $v1, 24($s1)
- sd $a0, 32($s1)
- sd $a1, 40($s1)
- sd $a2, 48($s1)
- sd $a3, 56($s1)
- sd $a4, 64($s1)
- sd $a5, 72($s1)
- sd $a6, 80($s1)
- sd $a7, 88($s1)
- sd $t0, 96($s1)
- sd $t1, 104($s1)
- sd $t2, 112($s1)
- sd $t3, 120($s1)
-
- ld $s0, 64($sp)
- ld $s1, 72($sp)
- ld $s2, 80($sp)
- ld $ra, 88($sp)
-
- daddiu $sp, $sp, 96
-
- j $ra
diff --git a/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp b/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
deleted file mode 100644
index 9fb0a28..0000000
--- a/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
- * COPYRIGHT OWNER 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.
- */
-
-#include <errno.h>
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include <android/log.h>
-#include <cutils/ashmem.h>
-
-#include "codeflinger/ARMAssemblerInterface.h"
-#include "codeflinger/MIPS64Assembler.h"
-
-using namespace android;
-
-#define TESTS_DATAOP_ENABLE 1
-#define TESTS_DATATRANSFER_ENABLE 1
-#define ASSEMBLY_SCRATCH_SIZE 4096
-
-void *instrMem;
-uint32_t instrMemSize = 128 * 1024;
-char dataMem[8192];
-
-typedef void (*asm_function_t)();
-extern "C" void asm_mips_test_jacket(asm_function_t function,
- int64_t regs[], int32_t flags[]);
-
-#define MAX_32BIT (uint32_t)(((uint64_t)1 << 32) - 1)
-#define MAX_64BIT ((uint64_t)0xFFFFFFFFFFFFFFFF)
-const uint32_t NA = 0;
-const uint32_t NUM_REGS = 32;
-const uint32_t NUM_FLAGS = 16;
-
-enum instr_t
-{
- INSTR_ADD,
- INSTR_SUB,
- INSTR_AND,
- INSTR_ORR,
- INSTR_RSB,
- INSTR_BIC,
- INSTR_CMP,
- INSTR_MOV,
- INSTR_MVN,
- INSTR_MUL,
- INSTR_MLA,
- INSTR_SMULBB,
- INSTR_SMULBT,
- INSTR_SMULTB,
- INSTR_SMULTT,
- INSTR_SMULWB,
- INSTR_SMULWT,
- INSTR_SMLABB,
- INSTR_UXTB16,
- INSTR_UBFX,
- INSTR_ADDR_ADD,
- INSTR_ADDR_SUB,
- INSTR_LDR,
- INSTR_LDRB,
- INSTR_LDRH,
- INSTR_ADDR_LDR,
- INSTR_LDM,
- INSTR_STR,
- INSTR_STRB,
- INSTR_STRH,
- INSTR_ADDR_STR,
- INSTR_STM
-};
-
-enum shift_t
-{
- SHIFT_LSL,
- SHIFT_LSR,
- SHIFT_ASR,
- SHIFT_ROR,
- SHIFT_NONE
-};
-
-enum offset_t
-{
- REG_SCALE_OFFSET,
- REG_OFFSET,
- IMM8_OFFSET,
- IMM12_OFFSET,
- NO_OFFSET
-};
-
-enum cond_t
-{
- EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV,
- HS = CS,
- LO = CC
-};
-
-const char * cc_code[] =
-{
- "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC",
- "HI", "LS","GE","LT", "GT", "LE", "AL", "NV"
-};
-
-struct condTest_t
-{
- int mode;
- int32_t Rcond1;
- int32_t Rcond2;
- uint64_t Rcond1Value;
- uint64_t Rcond2Value;
-};
-
-
-struct dataOpTest_t
-{
- uint32_t id;
- instr_t op;
- condTest_t preCond;
- cond_t cond;
- bool setFlags;
- uint64_t RnValue;
- uint64_t RsValue;
- bool immediate;
- uint32_t immValue;
- uint64_t RmValue;
- uint32_t shiftMode;
- uint32_t shiftAmount;
- uint64_t RdValue;
- bool checkRd;
- uint64_t postRdValue;
-};
-
-struct dataTransferTest_t
-{
- uint32_t id;
- instr_t op;
- uint32_t preFlag;
- cond_t cond;
- bool setMem;
- uint64_t memOffset;
- uint64_t memValue;
- uint64_t RnValue;
- offset_t offsetType;
- uint64_t RmValue;
- uint32_t immValue;
- bool writeBack;
- bool preIndex;
- bool postIndex;
- uint64_t RdValue;
- uint64_t postRdValue;
- uint64_t postRnValue;
- bool checkMem;
- uint64_t postMemOffset;
- uint32_t postMemLength;
- uint64_t postMemValue;
-};
-
-
-dataOpTest_t dataOpTests [] =
-{
- {0xA000,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,NA,NA,NA,NA,1,0},
- {0xA001,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,NA,NA,NA,NA,1,MAX_64BIT},
- {0xA002,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,NA,NA,NA,1,0},
- {0xA003,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT-1,NA,NA,NA,1,MAX_64BIT},
- {0xA004,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL, 0,NA,1,0},
- {0xA005,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000001},
- {0xA006,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,2},
- {0xA007,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,2},
- {0xA008,INSTR_ADD,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
- {0xA009,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,0},
- {0xA010,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,0,0,0,NA,1,1},
- {0xA011,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,0,0,0,NA,1,0},
- {0xA012,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,0,0,NA,1,1},
- {0xA013,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT-1,0,0,NA,1,0},
- {0xA014,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,0,NA,1,1},
- {0xA015,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0},
- {0xA016,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,1},
- {0xA017,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1},
- {0xA018,INSTR_AND,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,0},
- {0xA019,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_ASR,31,NA,1,1},
- {0xA020,INSTR_ORR,{0,0,0,0,0},AL,0,3,NA,1,MAX_32BIT,0,0,0,NA,1,MAX_64BIT},
- {0xA021,INSTR_ORR,{0,0,0,0,0},AL,0,2,NA,1,MAX_32BIT-1,0,0,0,NA,1,MAX_64BIT-1},
- {0xA022,INSTR_ORR,{0,0,0,0,0},AL,0,3,NA,0,0,MAX_32BIT,0,0,NA,1,MAX_64BIT},
- {0xA023,INSTR_ORR,{0,0,0,0,0},AL,0,2,NA,0,0,MAX_32BIT-1,0,0,NA,1,MAX_64BIT-1},
- {0xA024,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,0,NA,1,MAX_64BIT},
- {0xA025,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000001},
- {0xA026,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,1},
- {0xA027,INSTR_ORR,{0,0,0,0,0},AL,0,0,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1},
- {0xA028,INSTR_ORR,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
- {0xA029,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,MAX_64BIT},
- {0xA030,INSTR_CMP,{0,0,0,0,0},AL,1,0x10000,NA,1,0x10000,0,0,0,NA,0,0},
- {0xA031,INSTR_MUL,{0,0,0,0,0},AL,0,0,0x10000,0,0,0x10000,0,0,NA,1,0},
- {0xA032,INSTR_MUL,{0,0,0,0,0},AL,0,0,0x1000,0,0,0x10000,0,0,NA,1,0x10000000},
- {0xA033,INSTR_MUL,{0,0,0,0,0},AL,0,0,MAX_32BIT,0,0,1,0,0,NA,1,MAX_64BIT},
- {0xA034,INSTR_MLA,{0,0,0,0,0},AL,0,0x10000,0x10000,0,0,0x10000,0,0,NA,1,0x10000},
- {0xA035,INSTR_MLA,{0,0,0,0,0},AL,0,0x10000,0x1000,0,0,0x10000,0,0,NA,1,0x10010000},
- {0xA036,INSTR_SUB,{1,R_v1,R_a6,2,4},MI,0,2,NA,0,NA,1,NA,NA,2,1,1},
- {0xA037,INSTR_SUB,{2,R_v1,R_a6,2,0},MI,0,2,NA,0,NA,1,NA,NA,2,1,2},
- {0xA038,INSTR_SUB,{1,R_v1,R_a6,4,2},GE,0,2,NA,1,1,NA,NA,NA,2,1,1},
- {0xA039,INSTR_SUB,{1,R_a5,R_a6,2,7},GE,0,2,NA,1,1,NA,NA,NA,2,1,2},
- {0xA040,INSTR_SUB,{1,R_a5,R_a6,1,1},HS,0,2,NA,1,1,NA,NA,NA,2,1,1},
- {0xA041,INSTR_SUB,{1,R_a5,R_a6,0,1},HS,0,2,NA,1,1,NA,NA,NA,2,1,2},
- {0xA042,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,1,1<< 16,0,0,0,NA,1,UINT64_C(1) -(1<<16)},
- {0xA043,INSTR_SUB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,1,1,0,0,0,NA,1,MAX_64BIT-1},
- {0xA044,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,1,1,0,0,0,NA,1,0},
- {0xA045,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,1<<16,0,0,NA,1,UINT64_C(1) -(1<<16)},
- {0xA046,INSTR_SUB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,0,NA,1,0,0,NA,1,MAX_64BIT-1},
- {0xA047,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,0,0,NA,1,0},
- {0xA048,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,SHIFT_LSL,16,NA,1,UINT64_C(1) -(1<<16)},
- {0xA049,INSTR_SUB,{0,0,0,0,0},AL,0,0x80000001,NA,0,NA,MAX_32BIT,SHIFT_LSL,31,NA,1,1},
- {0xA050,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,3,SHIFT_LSR,1,NA,1,0},
- {0xA051,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,SHIFT_LSR,31,NA,1,0},
- {0xA052,INSTR_RSB,{1,R_a5,R_a6,4,1},GE,0,2,NA,1,0,NA,NA,NA,2,1,UINT64_C(-2)},
- {0xA053,INSTR_RSB,{1,R_a5,R_a6,UINT64_C(-1),1},GE,0,2,NA,1,0,NA,NA,NA,2,1,2},
- {0xA054,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,1,1<<16,NA,NA,NA,NA,1,(1<<16)-1},
- {0xA055,INSTR_RSB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,1,1,NA,NA,NA,NA,1,UINT64_C(1)-MAX_64BIT},
- {0xA056,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,1,1,NA,NA,NA,NA,1,0},
- {0xA057,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1<<16,0,0,NA,1,(1<<16)-1},
- {0xA058,INSTR_RSB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,0,NA,1,0,0,NA,1,UINT64_C(1)-MAX_64BIT},
- {0xA059,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,0,0,NA,1,0},
- {0xA060,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,SHIFT_LSL,16,NA,1,(1<<16)-1},
- {0xA061,INSTR_RSB,{0,0,0,0,0},AL,0,0x80000001,NA,0,NA,MAX_32BIT ,SHIFT_LSL,31,NA,1,UINT64_C(-1)},
- {0xA062,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,3,SHIFT_LSR,1,NA,1,0},
- {0xA063,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,SHIFT_LSR,31,NA,1,0},
- {0xA064,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,1,0x80000001,NA,NA,NA,NA,1,0xFFFFFFFF80000001},
- {0xA065,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,0x80000001,0,0,NA,1,0xFFFFFFFF80000001},
- {0xA066,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,NA,1,MAX_64BIT-1},
- {0xA067,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000000},
- {0xA068,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_LSR,1,NA,1,1},
- {0xA069,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1},
- {0xA070,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
- {0xA071,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_64BIT ,SHIFT_ASR,31,NA,1,MAX_64BIT},
- {0xA072,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_ROR,1,NA,1,0xFFFFFFFF80000001},
- {0xA073,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,0x80000001,SHIFT_ROR,31,NA,1,3},
- {0xA074,INSTR_MOV,{0,0,0,0,0},AL,1,NA,NA,0,0,MAX_64BIT -1,SHIFT_ASR,1,NA,1,MAX_64BIT},
- {0xA075,INSTR_MOV,{0,0,0,0,0},AL,1,NA,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
- {0xA076,INSTR_MOV,{2,R_a5,R_a6,6,8},MI,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
- {0xA077,INSTR_MOV,{2,R_a5,R_a6,UINT64_C(-4),UINT64_C(-8)},MI,0,NA,NA,0,0,0x80000001,0,0,2,1,0xFFFFFFFF80000001},
- {0xA078,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),UINT64_C(-1)},LT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
- {0xA079,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),1},LT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
- {0xA080,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),UINT64_C(-5)},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,MAX_64BIT-1},
- {0xA081,INSTR_MOV,{1,R_a5,R_a6,5,5},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,0xFFFFFFFF80000000},
- {0xA082,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),1},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,2},
- {0xA083,INSTR_MOV,{1,R_a5,R_a6,4,1},LE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,2},
- {0xA084,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),UINT64_C(-1)},LE,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
- {0xA085,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),1},LE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,0xFFFFFFFF80000000},
- {0xA086,INSTR_MOV,{1,R_a5,R_a6,1,1},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
- {0xA087,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),UINT64_C(-3)},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
- {0xA088,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),0},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
- {0xA089,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),UINT64_C(-1)},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,2},
- {0xA090,INSTR_MOV,{1,R_a5,R_a6,6,1},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,0xFFFFFFFF80000001},
- {0xA091,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),1},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,2},
- {0xA092,INSTR_MOV,{1,R_a5,R_a6,1,1},GT,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,2},
- {0xA093,INSTR_MOV,{1,R_a5,R_a6,4,1},GT,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,MAX_64BIT-1},
- {0xA094,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),1},GT,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,1,2,1,2},
- {0xA095,INSTR_MOV,{1,R_a5,R_a6,1,UINT64_C(-1)},HS,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
- {0xA096,INSTR_MOV,{1,R_a5,R_a6,UINT64_C(-1),1},HS,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
- {0xA097,INSTR_MVN,{1,R_a5,R_a6,1,4},HS,0,NA,NA,1,MAX_32BIT-1,NA,NA,NA,2,1,2},
- {0xA098,INSTR_MVN,{1,R_a5,R_a6,UINT64_C(-1),1},HS,0,NA,NA,1,MAX_32BIT-1,NA,NA,NA,2,1,1},
- {0xA099,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,1,0,NA,NA,NA,2,1,MAX_64BIT},
- {0xA100,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,0,NA,MAX_32BIT-1,NA,0,2,1,1},
- {0xA101,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,0,NA,0x80000001,NA,0,2,1,0x7FFFFFFE},
- {0xA102,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,NA,NA,NA,NA,1,0},
- {0xA103,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,NA,NA,NA,NA,1,1},
- {0xA104,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,0,0,NA,1,0},
- {0xA105,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT-1,0,0,NA,1,1},
- {0xA106,INSTR_BIC,{0,0,0,0,0},AL,0,0xF0,NA,0,0,3,SHIFT_ASR,1,NA,1,0xF0},
- {0xA107,INSTR_BIC,{0,0,0,0,0},AL,0,0xF0,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,0},
- {0xA108,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
- {0xA109,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00000FFF},
- {0xA110,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
- {0xA111,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,1},
- {0xA112,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
- {0xA113,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00000FFF},
- {0xA114,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
- {0xA115,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,1},
- {0xA116,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
- {0xA117,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
- {0xA118,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
- {0xA119,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,1},
- {0xA120,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
- {0xA121,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
- {0xA122,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
- {0xA123,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,1},
- {0xA124,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE},
- {0xA125,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
- {0xA126,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
- {0xA127,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0},
- {0xA128,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE},
- {0xA129,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
- {0xA130,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
- {0xA131,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0},
- {0xA132,INSTR_SMLABB,{0,0,0,0,0},AL,0,1,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0},
- {0xA133,INSTR_SMLABB,{0,0,0,0,0},AL,0,1,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00001000},
- {0xA134,INSTR_SMLABB,{0,0,0,0,0},AL,0,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFABCD0001,0,NA,0xABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE},
- {0xA135,INSTR_SMLABB,{0,0,0,0,0},AL,0,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFABCDFFFF,0,NA,0xABCDFFFF,NA,NA,NA,1,0},
- {0xA136,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,0,NA,1,0x00CD0001},
- {0xA137,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,1,NA,1,0x00AB00EF},
- {0xA138,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,2,NA,1,0x000100CD},
- {0xA139,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,3,NA,1,0x00EF00AB},
- {0xA140,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x1,SHIFT_LSL,1,NA,1,0xD00000001},
- {0xA141,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0x01,NA,0,NA,0x1,SHIFT_LSL,2,NA,1,0x5},
- {0xA142,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x1,NA,0,NA,1,0xD00000000},
- {0xA143,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,0xD00000001,NA,0,NA,0x010000,SHIFT_LSR,15,NA,1,0xCFFFFFFFF},
- {0xA144,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x020000,SHIFT_LSR,15,NA,1,0xCFFFFFFFB},
- {0xA145,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,3,NA,0,NA,0x010000,SHIFT_LSR,15,NA,1,1},
-};
-
-dataTransferTest_t dataTransferTests [] =
-{
- {0xB000,INSTR_LDR,AL,AL,1,24,0xABCDEF0123456789,0,REG_SCALE_OFFSET,24,NA,NA,NA,NA,NA,0x23456789,0,0,NA,NA,NA},
- {0xB001,INSTR_LDR,AL,AL,1,0,0xABCDEF0123456789,0,IMM12_OFFSET,NA,4,1,0,1,NA,0x23456789,4,0,NA,NA,NA},
- {0xB002,INSTR_LDR,AL,AL,1,0,0xABCDEF0123456789,0,NO_OFFSET,NA,NA,0,0,0,NA,0x23456789,0,0,NA,NA,NA},
- {0xB003,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,0,REG_SCALE_OFFSET,4064,NA,NA,NA,NA,NA,0x89,0,0,NA,NA,NA},
- {0xB004,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,0,0,1,0,NA,0x67,4065,0,NA,NA,NA},
- {0xB005,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,1,0,1,0,NA,0x45,4065,0,NA,NA,NA},
- {0xB006,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,2,0,1,0,NA,0x23,4065,0,NA,NA,NA},
- {0xB007,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,1,1,0,1,NA,0x67,4066,0,NA,NA,NA},
- {0xB008,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,0,NO_OFFSET,NA,NA,0,0,0,NA,0x89,0,0,NA,NA,NA},
- {0xB009,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,0,IMM8_OFFSET,NA,2,1,0,1,NA,0x6789,2,0,NA,NA,NA},
- {0xB010,INSTR_LDRH,AL,AL,1,4064,0xABCDEF0123456789,0,REG_OFFSET,4064,0,0,1,0,NA,0x6789,0,0,NA,NA,NA},
- {0xB011,INSTR_LDRH,AL,AL,1,4064,0xABCDEF0123456789,0,REG_OFFSET,4066,0,0,1,0,NA,0x2345,0,0,NA,NA,NA},
- {0xB012,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,0,NO_OFFSET,NA,0,0,0,0,NA,0x6789,0,0,NA,NA,NA},
- {0xB013,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,2,NO_OFFSET,NA,0,0,0,0,NA,0x2345,2,0,NA,NA,NA},
- {0xB014,INSTR_STR,AL,AL,1,2,0xDEADBEEFDEADBEEF,4,IMM12_OFFSET,NA,4,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,8,1,2,8,0xDEAD23456789BEEF},
- {0xB015,INSTR_STR,AL,AL,1,2,0xDEADBEEFDEADBEEF,4,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4,1,2,8,0xDEAD23456789BEEF},
- {0xB016,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,0,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDEAD89EF},
- {0xB017,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,1,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDE89BEEF},
- {0xB018,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,2,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEF89ADBEEF},
- {0xB019,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,4,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,5,1,0,8,0xDEADBEEFDEAD89EF},
- {0xB020,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDEAD89EF},
- {0xB021,INSTR_STRH,AL,AL,1,4066,0xDEADBEEFDEADBEEF,4070,IMM8_OFFSET,NA,2,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,4072,1,4066,8,0xDEAD6789DEADBEEF},
- {0xB022,INSTR_STRH,AL,AL,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEAD6789DEADBEEF},
-};
-
-
-void flushcache()
-{
- const long base = long(instrMem);
- const long curr = base + long(instrMemSize);
- __builtin___clear_cache((char*)base, (char*)curr);
-}
-
-void dataOpTest(dataOpTest_t test, ArmToMips64Assembler *a64asm, uint32_t Rd = R_v1,
- uint32_t Rn = R_t0, uint32_t Rm = R_t1, uint32_t Rs = R_t2)
-{
- int64_t regs[NUM_REGS] = {0};
- int32_t flags[NUM_FLAGS] = {0};
- int64_t savedRegs[NUM_REGS] = {0};
- uint32_t i;
- uint32_t op2;
-
- for(i = 0; i < NUM_REGS; ++i)
- {
- regs[i] = i;
- }
-
- regs[Rd] = test.RdValue;
- regs[Rn] = test.RnValue;
- regs[Rs] = test.RsValue;
- a64asm->reset();
- if (test.preCond.mode) {
- a64asm->set_condition(test.preCond.mode, test.preCond.Rcond1, test.preCond.Rcond2);
- regs[test.preCond.Rcond1] = test.preCond.Rcond1Value;
- regs[test.preCond.Rcond2] = test.preCond.Rcond2Value;
- }
- a64asm->prolog();
- if(test.immediate == true)
- {
- op2 = a64asm->imm(test.immValue);
- }
- else if(test.immediate == false && test.shiftAmount == 0)
- {
- op2 = Rm;
- regs[Rm] = (int64_t)((int32_t)(test.RmValue));
- }
- else
- {
- op2 = a64asm->reg_imm(Rm, test.shiftMode, test.shiftAmount);
- regs[Rm] = (int64_t)((int32_t)(test.RmValue));
- }
- switch(test.op)
- {
- case INSTR_ADD: a64asm->ADD(test.cond, test.setFlags, Rd,Rn,op2); break;
- case INSTR_SUB: a64asm->SUB(test.cond, test.setFlags, Rd,Rn,op2); break;
- case INSTR_RSB: a64asm->RSB(test.cond, test.setFlags, Rd,Rn,op2); break;
- case INSTR_AND: a64asm->AND(test.cond, test.setFlags, Rd,Rn,op2); break;
- case INSTR_ORR: a64asm->ORR(test.cond, test.setFlags, Rd,Rn,op2); break;
- case INSTR_BIC: a64asm->BIC(test.cond, test.setFlags, Rd,Rn,op2); break;
- case INSTR_MUL: a64asm->MUL(test.cond, test.setFlags, Rd,Rm,Rs); break;
- case INSTR_MLA: a64asm->MLA(test.cond, test.setFlags, Rd,Rm,Rs,Rn); break;
- case INSTR_CMP: a64asm->CMP(test.cond, Rn,op2); break;
- case INSTR_MOV: a64asm->MOV(test.cond, test.setFlags,Rd,op2); break;
- case INSTR_MVN: a64asm->MVN(test.cond, test.setFlags,Rd,op2); break;
- case INSTR_SMULBB:a64asm->SMULBB(test.cond, Rd,Rm,Rs); break;
- case INSTR_SMULBT:a64asm->SMULBT(test.cond, Rd,Rm,Rs); break;
- case INSTR_SMULTB:a64asm->SMULTB(test.cond, Rd,Rm,Rs); break;
- case INSTR_SMULTT:a64asm->SMULTT(test.cond, Rd,Rm,Rs); break;
- case INSTR_SMULWB:a64asm->SMULWB(test.cond, Rd,Rm,Rs); break;
- case INSTR_SMULWT:a64asm->SMULWT(test.cond, Rd,Rm,Rs); break;
- case INSTR_SMLABB:a64asm->SMLABB(test.cond, Rd,Rm,Rs,Rn); break;
- case INSTR_UXTB16:a64asm->UXTB16(test.cond, Rd,Rm,test.shiftAmount); break;
- case INSTR_ADDR_ADD: a64asm->ADDR_ADD(test.cond, test.setFlags, Rd,Rn,op2); break;
- case INSTR_ADDR_SUB: a64asm->ADDR_SUB(test.cond, test.setFlags, Rd,Rn,op2); break;
- default: printf("Error"); return;
- }
- a64asm->epilog(0);
- a64asm->fix_branches();
- flushcache();
-
- asm_function_t asm_function = (asm_function_t)(instrMem);
-
- for(i = 0; i < NUM_REGS; ++i)
- savedRegs[i] = regs[i];
-
- asm_mips_test_jacket(asm_function, regs, flags);
-
- /* Check if all regs except Rd is same */
- for(i = 0; i < NUM_REGS; ++i)
- {
- if((i == Rd) || i == 2) continue;
- if(regs[i] != savedRegs[i])
- {
- printf("Test %x failed Reg(%d) tampered Expected(0x%" PRIx64 "),"
- "Actual(0x%" PRIx64 ") t\n", test.id, i, savedRegs[i],
- regs[i]);
- exit(0);
- return;
- }
- }
-
- if(test.checkRd == 1 && regs[Rd] != test.postRdValue)
- {
- printf("Test %x failed, Expected(%" PRIx64 "), Actual(%" PRIx64 ")\n",
- test.id, test.postRdValue, regs[Rd]);
- exit(0);
- }
- else
- {
- printf("Test %x passed\n", test.id);
- }
-}
-
-
-void dataTransferTest(dataTransferTest_t test, ARMAssemblerInterface *a64asm,
- uint32_t Rd = R_v1, uint32_t Rn = R_t0,uint32_t Rm = R_t1)
-{
- int64_t regs[NUM_REGS] = {0};
- int64_t savedRegs[NUM_REGS] = {0};
- int32_t flags[NUM_FLAGS] = {0};
- uint32_t i;
- for(i = 0; i < NUM_REGS; ++i)
- {
- regs[i] = i;
- }
-
- uint32_t op2;
-
- regs[Rd] = test.RdValue;
- regs[Rn] = (uint64_t)(&dataMem[test.RnValue]);
- regs[Rm] = test.RmValue;
- flags[test.preFlag] = 1;
-
- if(test.setMem == true)
- {
- unsigned char *mem = (unsigned char *)&dataMem[test.memOffset];
- uint64_t value = test.memValue;
- for(int j = 0; j < 8; ++j)
- {
- mem[j] = value & 0x00FF;
- value >>= 8;
- }
- }
- a64asm->reset();
- a64asm->prolog();
- if(test.offsetType == REG_SCALE_OFFSET)
- {
- op2 = a64asm->reg_scale_pre(Rm);
- }
- else if(test.offsetType == REG_OFFSET)
- {
- op2 = a64asm->reg_pre(Rm);
- }
- else if(test.offsetType == IMM12_OFFSET && test.preIndex == true)
- {
- op2 = a64asm->immed12_pre(test.immValue, test.writeBack);
- }
- else if(test.offsetType == IMM12_OFFSET && test.postIndex == true)
- {
- op2 = a64asm->immed12_post(test.immValue);
- }
- else if(test.offsetType == IMM8_OFFSET && test.preIndex == true)
- {
- op2 = a64asm->immed8_pre(test.immValue, test.writeBack);
- }
- else if(test.offsetType == IMM8_OFFSET && test.postIndex == true)
- {
- op2 = a64asm->immed8_post(test.immValue);
- }
- else if(test.offsetType == NO_OFFSET)
- {
- op2 = a64asm->__immed12_pre(0);
- }
- else
- {
- printf("Error - Unknown offset\n"); return;
- }
-
- switch(test.op)
- {
- case INSTR_LDR: a64asm->LDR(test.cond, Rd,Rn,op2); break;
- case INSTR_LDRB: a64asm->LDRB(test.cond, Rd,Rn,op2); break;
- case INSTR_LDRH: a64asm->LDRH(test.cond, Rd,Rn,op2); break;
- case INSTR_ADDR_LDR: a64asm->ADDR_LDR(test.cond, Rd,Rn,op2); break;
- case INSTR_STR: a64asm->STR(test.cond, Rd,Rn,op2); break;
- case INSTR_STRB: a64asm->STRB(test.cond, Rd,Rn,op2); break;
- case INSTR_STRH: a64asm->STRH(test.cond, Rd,Rn,op2); break;
- case INSTR_ADDR_STR: a64asm->ADDR_STR(test.cond, Rd,Rn,op2); break;
- default: printf("Error"); return;
- }
- a64asm->epilog(0);
- flushcache();
-
- asm_function_t asm_function = (asm_function_t)(instrMem);
-
- for(i = 0; i < NUM_REGS; ++i)
- savedRegs[i] = regs[i];
-
- asm_mips_test_jacket(asm_function, regs, flags);
-
- /* Check if all regs except Rd/Rn are same */
- for(i = 0; i < NUM_REGS; ++i)
- {
- if(i == Rd || i == Rn || i == R_v0) continue;
-
- if(regs[i] != savedRegs[i])
- {
- printf("Test %x failed Reg(%d) tampered"
- " Expected(0x%" PRIx64 "), Actual(0x%" PRIx64 ") t\n",
- test.id, i, savedRegs[i], regs[i]);
- return;
- }
- }
-
- if((uint64_t)regs[Rd] != test.postRdValue)
- {
- printf("Test %x failed, "
- "Expected in Rd(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
- test.id, test.postRdValue, regs[Rd]);
- }
- else if((uint64_t)regs[Rn] != (uint64_t)(&dataMem[test.postRnValue]))
- {
- printf("Test %x failed, "
- "Expected in Rn(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
- test.id, test.postRnValue, regs[Rn] - (uint64_t)dataMem);
- }
- else if(test.checkMem == true)
- {
- unsigned char *addr = (unsigned char *)&dataMem[test.postMemOffset];
- uint64_t value;
- value = 0;
- for(uint32_t j = 0; j < test.postMemLength; ++j)
- value = (value << 8) | addr[test.postMemLength-j-1];
- if(value != test.postMemValue)
- {
- printf("Test %x failed, "
- "Expected in Mem(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
- test.id, test.postMemValue, value);
- }
- else
- {
- printf("Test %x passed\n", test.id);
- }
- }
- else
- {
- printf("Test %x passed\n", test.id);
- }
-}
-
-int main(void)
-{
- uint32_t i;
-
- /* Allocate memory to store instructions generated by ArmToArm64Assembler */
- {
- int fd = ashmem_create_region("code cache", instrMemSize);
- if(fd < 0) {
- printf("IF < 0\n");
- printf("Creating code cache, ashmem_create_region "
- "failed with error '%s'", strerror(errno));
- }
- instrMem = mmap(NULL, instrMemSize,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE, fd, 0);
- }
-
- ArmToMips64Assembler a64asm(instrMem);
-
- if(TESTS_DATAOP_ENABLE)
- {
- printf("Running data processing tests\n");
- for(i = 0; i < sizeof(dataOpTests)/sizeof(dataOpTest_t); ++i) {
- dataOpTest(dataOpTests[i], &a64asm);
- }
- }
-
- if(TESTS_DATATRANSFER_ENABLE)
- {
- printf("Running data transfer tests\n");
- for(i = 0; i < sizeof(dataTransferTests)/sizeof(dataTransferTest_t); ++i)
- dataTransferTest(dataTransferTests[i], &a64asm);
- }
-
- return 0;
-}
diff --git a/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.bp b/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.bp
deleted file mode 100644
index bfc6ae9..0000000
--- a/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.bp
+++ /dev/null
@@ -1,6 +0,0 @@
-cc_test {
- name: "test-pixelflinger-mips64-col32cb16blend",
- defaults: ["pixelflinger-tests-mips64"],
-
- srcs: ["col32cb16blend_test.c"],
-}
diff --git a/libpixelflinger/tests/arch-mips64/col32cb16blend/col32cb16blend_test.c b/libpixelflinger/tests/arch-mips64/col32cb16blend/col32cb16blend_test.c
deleted file mode 100644
index 066eab6..0000000
--- a/libpixelflinger/tests/arch-mips64/col32cb16blend/col32cb16blend_test.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
- * COPYRIGHT OWNER 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.
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-
-
-#define ARGB_8888_MAX 0xFFFFFFFF
-#define ARGB_8888_MIN 0x00000000
-#define RGB_565_MAX 0xFFFF
-#define RGB_565_MIN 0x0000
-
-struct test_t
-{
- char name[256];
- uint32_t src_color;
- uint16_t dst_color;
- size_t count;
-};
-
-struct test_t tests[] =
-{
- {"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
- {"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
- {"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
- {"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
- {"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
- {"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
- {"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
- {"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
- {"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
- {"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
-};
-
-void scanline_col32cb16blend_mips64(uint16_t *dst, uint32_t src, size_t count);
-void scanline_col32cb16blend_c(uint16_t * dst, uint32_t src, size_t count)
-{
- uint32_t srcAlpha = (src>>24);
- uint32_t f = 0x100 - (srcAlpha + (srcAlpha>>7));
-
- while (count--)
- {
- uint16_t d = *dst;
- int dstR = (d>>11)&0x1f;
- int dstG = (d>>5)&0x3f;
- int dstB = (d)&0x1f;
- int srcR = (src >> ( 3))&0x1F;
- int srcG = (src >> ( 8+2))&0x3F;
- int srcB = (src >> (16+3))&0x1F;
- srcR += (f*dstR)>>8;
- srcG += (f*dstG)>>8;
- srcB += (f*dstB)>>8;
- *dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
- }
-}
-
-void scanline_col32cb16blend_test()
-{
- uint16_t dst_c[16], dst_asm[16];
- uint32_t i, j;
-
- for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
- {
- struct test_t test = tests[i];
-
- printf("Testing - %s:",test.name);
-
- memset(dst_c, 0, sizeof(dst_c));
- memset(dst_asm, 0, sizeof(dst_asm));
-
- for(j = 0; j < test.count; ++j)
- {
- dst_c[j] = test.dst_color;
- dst_asm[j] = test.dst_color;
- }
-
-
- scanline_col32cb16blend_c(dst_c, test.src_color, test.count);
- scanline_col32cb16blend_mips64(dst_asm, test.src_color, test.count);
-
- if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
- printf("Passed\n");
- else
- printf("Failed\n");
-
- for(j = 0; j < test.count; ++j)
- {
- printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
- }
- }
-}
-
-int main()
-{
- scanline_col32cb16blend_test();
- return 0;
-}
diff --git a/libpixelflinger/tests/arch-mips64/disassembler/Android.bp b/libpixelflinger/tests/arch-mips64/disassembler/Android.bp
deleted file mode 100644
index 96bf9e9..0000000
--- a/libpixelflinger/tests/arch-mips64/disassembler/Android.bp
+++ /dev/null
@@ -1,6 +0,0 @@
-cc_test {
- name: "test-pixelflinger-mips64-disassembler-test",
- defaults: ["pixelflinger-tests-mips64"],
-
- srcs: ["mips64_disassembler_test.cpp"],
-}
diff --git a/libpixelflinger/tests/arch-mips64/disassembler/mips64_disassembler_test.cpp b/libpixelflinger/tests/arch-mips64/disassembler/mips64_disassembler_test.cpp
deleted file mode 100644
index 22efa9f..0000000
--- a/libpixelflinger/tests/arch-mips64/disassembler/mips64_disassembler_test.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
- * COPYRIGHT OWNER 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.
- */
-#include <stdio.h>
-#include <inttypes.h>
-#include <string.h>
-#include "../../../codeflinger/mips64_disassem.h"
-
-//typedef uint64_t db_addr_t;
-//db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_format);
-
-struct test_table_entry_t
-{
- uint32_t code;
- const char *instr;
-};
-
-static test_table_entry_t test_table [] =
-{
- { 0x00011020, "add\tv0,zero,at" },
- { 0x00832820, "add\ta1,a0,v1" },
- { 0x00c74020, "add\ta4,a2,a3" },
- { 0x012a5820, "add\ta7,a5,a6" },
- { 0x258dffff, "addiu\tt1,t0,-1" },
- { 0x25cf0004, "addiu\tt3,t2,4" },
- { 0x02119021, "addu\ts2,s0,s1" },
- { 0x0274a821, "addu\ts5,s3,s4" },
- { 0x02d7c024, "and\tt8,s6,s7" },
- { 0x333aff00, "andi\tk0,t9,0xff00" },
- { 0x3f7cffff, "aui\tgp,k1,-1" },
- { 0x3c1dffff, "lui\tsp,0xffff" },
- { 0x00e04051, "clo\ta4,a3" },
- { 0x01205050, "clz\ta6,a5" },
- { 0x016c682c, "dadd\tt1,a7,t0" },
- { 0x65cf0008, "daddiu\tt3,t2,8" },
- { 0x0211902d, "daddu\ts2,s0,s1" },
- { 0x7e741403, "dext\ts4,s3,16,3" },
- { 0x7eb6f801, "dextm\ts6,s5,0,64" },
- { 0x7ef87c02, "dextu\tt8,s7,48,16" },
- { 0x7f3a8207, "dins\tk0,t9,8,9" },
- { 0x7f7c0005, "dinsm\tgp,k1,0,33" },
- { 0x7fbe0806, "dinsu\ts8,sp,32,2" },
- { 0x03e1102e, "dsub\tv0,ra,at" },
- { 0x0064282f, "dsubu\ta1,v1,a0" },
- { 0x7cc77a00, "ext\ta3,a2,8,16" },
- { 0x7d09fc04, "ins\ta5,a4,16,16" },
- { 0x00200009, "jr\tat" },
- { 0x00201009, "jalr\tv0,at" },
- { 0x0020f809, "jalr\tat" },
- { 0x8082fff0, "lb\tv0,-16(a0)" },
- { 0x916c0008, "lbu\tt0,8(a7)" },
- { 0xdfa3ffe8, "ld\tv1,-24(sp)" },
- { 0x84850080, "lh\ta1,128(a0)" },
- { 0x94c7ff80, "lhu\ta3,-128(a2)" },
- { 0x8d09000c, "lw\ta5,12(a4)" },
- { 0x9d4bfff4, "lwu\ta7,-12(a6)" },
- { 0x00620898, "mul\tat,v1,v0" },
- { 0x006208d8, "muh\tat,v1,v0" },
- { 0x00620899, "mulu\tat,v1,v0" },
- { 0x006208d9, "muhu\tat,v1,v0" },
- { 0x00000000, "nop" },
- { 0x02329827, "nor\ts3,s1,s2" },
- { 0x0295b025, "or\ts6,s4,s5" },
- { 0x36f0ff00, "ori\ts0,s7,0xff00" },
- { 0x7c03103b, "rdhwr\tv0,v1" },
- { 0x00242a02, "rotr\ta1,a0,8" },
- { 0x00c74046, "rotrv\ta4,a3,a2" },
- { 0xa12afff0, "sb\ta6,-16(a5)" },
- { 0xfd6c0100, "sd\tt0,256(a7)" },
- { 0x7c0d7420, "seb\tt2,t1" },
- { 0x7c0f8620, "seh\ts0,t3" },
- { 0x02329835, "seleqz\ts3,s1,s2" },
- { 0x0295b037, "selnez\ts6,s4,s5" },
- { 0xa6f84000, "sh\tt8,16384(s7)" },
- { 0x0019d100, "sll\tk0,t9,4" },
- { 0x037ce804, "sllv\tsp,gp,k1" },
- { 0x03df082a, "slt\tat,s8,ra" },
- { 0x28430007, "slti\tv1,v0,7" },
- { 0x2c850020, "sltiu\ta1,a0,32" },
- { 0x00c7402b, "sltu\ta4,a2,a3" },
- { 0x00095103, "sra\ta6,a5,4" },
- { 0x016c6807, "srav\tt1,t0,a7" },
- { 0x000e7a02, "srl\tt3,t2,8" },
- { 0x02119006, "srlv\ts2,s1,s0" },
- { 0x0274a822, "sub\ts5,s3,s4" },
- { 0x02d7c023, "subu\tt8,s6,s7" },
- { 0xaf3afffc, "sw\tk0,-4(t9)" },
- { 0x7c1be0a0, "wsbh\tgp,k1" },
- { 0x03bef826, "xor\tra,sp,s8" },
- { 0x3801ffff, "li\tat,0xffff" },
- { 0x3843ffff, "xori\tv1,v0,0xffff" },
-};
-
-struct test_branches_table_entry_t
-{
- uint32_t code;
- const char *instr;
- int16_t offset;
-};
-
-static test_branches_table_entry_t test_branches_table [] = {
- { 0x1000ffff, "b\t", static_cast<int16_t>(0xffff) },
- { 0x13df0008, "beq\ts8,ra,", 0x8 },
- { 0x042100ff, "bgez\tat,", 0xff },
- { 0x1c40ff00, "bgtz\tv0,", static_cast<int16_t>(0xff00) },
- { 0x18605555, "blez\tv1,", 0x5555 },
- { 0x0480aaaa, "bltz\ta0,", static_cast<int16_t>(0xaaaa) },
- { 0x14a68888, "bne\ta1,a2,", static_cast<int16_t>(0x8888) },
-};
-
-struct test_jump_table_entry_t
-{
- uint32_t code;
- const char *instr;
- int32_t offset;
-};
-
-static test_jump_table_entry_t test_jump_table [] = {
- { 0x0956ae66, "j\t", 0x156ae66 },
- { 0x0d56ae66, "jal\t", 0x156ae66 },
-};
-
-int main()
-{
- char instr[256];
- uint32_t failed = 0;
-
- for(uint32_t i = 0; i < sizeof(test_table)/sizeof(test_table_entry_t); ++i)
- {
- test_table_entry_t *test;
- test = &test_table[i];
- mips_disassem(&test->code, instr, 0);
- if(strcmp(instr, test->instr) != 0)
- {
- printf("Test Failed \n"
- "Code : 0x%0x\n"
- "Expected : %s\n"
- "Actual : %s\n", test->code, test->instr, instr);
- failed++;
- }
- }
- for(uint32_t i = 0; i < sizeof(test_branches_table)/sizeof(test_branches_table_entry_t); ++i)
- {
- test_branches_table_entry_t *test;
- test = &test_branches_table[i];
- mips_disassem(&test->code, instr, 0);
- //printf("DBG code address: %lx\n", (uint64_t)(&test->code));
- uint64_t loc = (uint64_t)test + 4 + (test->offset << 2);
- //printf("DBG loc: %lx\n", loc);
- char temp[256], address[16];
- strcpy(temp, test->instr);
- sprintf(address, "0x%lx", loc);
- strcat(temp, address);
- if(strcmp(instr, temp) != 0)
- {
- printf("Test Failed \n"
- "Code : 0x%0x\n"
- "Expected : %s\n"
- "Actual : %s\n", test->code, temp, instr);
- failed++;
- }
- }
- for(uint32_t i = 0; i < sizeof(test_jump_table)/sizeof(test_jump_table_entry_t); ++i)
- {
- test_jump_table_entry_t *test;
- test = &test_jump_table[i];
- mips_disassem(&test->code, instr, 0);
- //printf("DBG code address: %lx\n", (uint64_t)(&test->code));
- uint64_t loc = ((uint64_t)test & 0xfffffffff0000000) | (test->offset << 2);
- //printf("DBG loc: %lx\n", loc);
- char temp[256], address[16];
- strcpy(temp, test->instr);
- sprintf(address, "0x%08lx", loc);
- strcat(temp, address);
- if(strcmp(instr, temp) != 0)
- {
- printf("Test Failed \n"
- "Code : 0x%0x\n"
- "Expected : '%s'\n"
- "Actual : '%s'\n", test->code, temp, instr);
- failed++;
- }
- }
- if(failed == 0)
- {
- printf("All tests PASSED\n");
- return 0;
- }
- else
- {
- printf("%d tests FAILED\n", failed);
- return -1;
- }
-}
diff --git a/libstats/push_compat/Android.bp b/libstats/push_compat/Android.bp
index 465c05a..fcd8c83 100644
--- a/libstats/push_compat/Android.bp
+++ b/libstats/push_compat/Android.bp
@@ -35,6 +35,8 @@
header_libs: ["libstatssocket_headers"],
static_libs: [
"libbase",
+ ],
+ shared_libs: [
"liblog",
"libutils",
],
diff --git a/rootdir/init.rc b/rootdir/init.rc
index fdc9d32..5ebffab 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -16,6 +16,11 @@
# Disable sysrq from keyboard
write /proc/sys/kernel/sysrq 0
+ # Android doesn't need kernel module autoloading, and it causes SELinux
+ # denials. So disable it by setting modprobe to the empty string. Note: to
+ # explicitly set a sysctl to an empty string, a trailing newline is needed.
+ write /proc/sys/kernel/modprobe \n
+
# Set the security context of /adb_keys if present.
restorecon /adb_keys