Fix GitHub Actions Build + Move Stack to Shared Memory

This commit mainly fixes GitHub Actions builds which were broken due to an outdated version of Android NDK. In addition, it moves all stack to shared memory.
This commit is contained in:
◱ PixelyIon 2020-03-23 21:40:22 +05:30 committed by ◱ PixelyIon
parent 38f63eced3
commit 5f072da2b8
11 changed files with 1585 additions and 33 deletions

View File

@ -37,7 +37,7 @@ jobs:
run: chmod +x gradlew
- name: Install CMake from Android SDK Manager
run: yes | sdkmanager --install "cmake;3.10.2.4988404" | grep -v = || true
run: yes | sdkmanager --install "ndk;21.0.6113669" "cmake;3.10.2.4988404" | grep -v = || true
- name: Android Lint
run: ./gradlew --stacktrace lint

View File

@ -3,9 +3,6 @@
<option name="RIGHT_MARGIN" value="400" />
<option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" />
<option name="SOFT_MARGINS" value="80,140" />
<AndroidXmlCodeStyleSettings>
<option name="ARRANGEMENT_SETTINGS_MIGRATED_TO_191" value="true" />
</AndroidXmlCodeStyleSettings>
<Objective-C>
<option name="INDENT_VISIBILITY_KEYWORDS" value="2" />
<option name="INDENT_PREPROCESSOR_DIRECTIVE" value="4" />

File diff suppressed because it is too large Load Diff

25
.idea/jsonSchemas.xml Normal file
View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JsonSchemaMappingsProjectConfiguration">
<state>
<map>
<entry key="github-workflow">
<value>
<SchemaInfo>
<option name="name" value="github-workflow" />
<option name="relativePathToSchema" value="http://json.schemastore.org/github-workflow" />
<option name="applicationDefined" value="true" />
<option name="patterns">
<list>
<Item>
<option name="path" value=".github/workflows/ci.yml" />
</Item>
</list>
</option>
</SchemaInfo>
</value>
</entry>
</map>
</state>
</component>
</project>

View File

@ -51,8 +51,8 @@ namespace skyline::kernel::type {
threads[pid]->tls = GetTlsSlot();
}
KProcess::KProcess(const DeviceState &state, pid_t pid, u64 entryPoint, u64 stackBase, u64 stackSize, std::shared_ptr<type::KSharedMemory> &tlsMemory) : pid(pid), KSyncObject(state, KType::KProcess) {
auto thread = NewHandle<KThread>(pid, entryPoint, 0x0, stackBase + stackSize, 0, constant::DefaultPriority, this, tlsMemory).item;
KProcess::KProcess(const DeviceState &state, pid_t pid, u64 entryPoint, std::shared_ptr<type::KSharedMemory> &stack, std::shared_ptr<type::KSharedMemory> &tlsMemory) : pid(pid), stack(stack), KSyncObject(state, KType::KProcess) {
auto thread = NewHandle<KThread>(pid, entryPoint, 0x0, stack->guest.address + stack->guest.size, 0, constant::DefaultPriority, this, tlsMemory).item;
threads[pid] = thread;
state.nce->WaitThreadInit(thread);
memFd = open(fmt::format("/proc/{}/mem", pid).c_str(), O_RDWR | O_CLOEXEC);

View File

@ -107,6 +107,7 @@ namespace skyline::kernel::type {
std::unordered_map<u64, std::vector<std::shared_ptr<WaitStatus>>> mutexes; //!< A map from a mutex's address to a vector of Mutex objects for threads waiting on it
std::unordered_map<u64, std::list<std::shared_ptr<WaitStatus>>> conditionals; //!< A map from a conditional variable's address to a vector of threads waiting on it
std::vector<std::shared_ptr<TlsPage>> tlsPages; //!< A vector of all allocated TLS pages
std::shared_ptr<type::KSharedMemory> stack; //!< The shared memory used to hold the stack of the main thread
std::shared_ptr<KPrivateMemory> heap; //!< The kernel memory object backing the allocated heap
Mutex mutexLock; //!< This mutex is to prevent concurrent mutex operations to happen at once
Mutex conditionalLock; //!< This mutex is to prevent concurrent conditional variable operations to happen at once
@ -116,11 +117,10 @@ namespace skyline::kernel::type {
* @param state The state of the device
* @param pid The PID of the main thread
* @param entryPoint The address to start execution at
* @param stackBase The base of the stack
* @param stackSize The size of the stack
* @param stack The KSharedMemory object for Stack memory allocated by the guest process
* @param tlsMemory The KSharedMemory object for TLS memory allocated by the guest process
*/
KProcess(const DeviceState &state, pid_t pid, u64 entryPoint, u64 stackBase, u64 stackSize, std::shared_ptr<type::KSharedMemory> &tlsMemory);
KProcess(const DeviceState &state, pid_t pid, u64 entryPoint, std::shared_ptr<type::KSharedMemory> &stack, std::shared_ptr<type::KSharedMemory> &tlsMemory);
/**
* Close the file descriptor to the process's memory

View File

@ -6,13 +6,13 @@
#include <asm/unistd.h>
namespace skyline::kernel::type {
KSharedMemory::KSharedMemory(const DeviceState &state, u64 address, size_t size, const memory::Permission permission, memory::MemoryState memState) : initialState(memState), KMemory(state, KType::KSharedMemory) {
KSharedMemory::KSharedMemory(const DeviceState &state, u64 address, size_t size, const memory::Permission permission, memory::MemoryState memState, int mmapFlags) : initialState(memState), KMemory(state, KType::KSharedMemory) {
if (address && !utils::PageAligned(address))
throw exception("KSharedMemory was created with non-page-aligned address: 0x{:X}", address);
fd = ASharedMemory_create("KSharedMemory", size);
if (fd < 0)
throw exception("An error occurred while creating shared memory: {}", fd);
address = reinterpret_cast<u64>(mmap(reinterpret_cast<void *>(address), size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | ((address) ? MAP_FIXED : 0), fd, 0));
address = reinterpret_cast<u64>(mmap(reinterpret_cast<void *>(address), size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | ((address) ? MAP_FIXED : 0) | mmapFlags, fd, 0));
if (address == reinterpret_cast<u64>(MAP_FAILED))
throw exception("An occurred while mapping shared memory: {}", strerror(errno));
kernel = {.address = address, .size = size, .permission = permission};

View File

@ -33,8 +33,9 @@ namespace skyline::kernel::type {
* @param size The size of the allocation on the kernel
* @param permission The permission of the kernel process
* @param memState The MemoryState of the chunk of memory
* @param mmapFlags Additional flags to pass to mmap
*/
KSharedMemory(const DeviceState &state, u64 address, size_t size, const memory::Permission permission, memory::MemoryState memState = memory::MemoryStates::SharedMemory);
KSharedMemory(const DeviceState &state, u64 address, size_t size, const memory::Permission permission, memory::MemoryState memState = memory::MemoryStates::SharedMemory, int mmapFlags = 0);
/**
* @brief Maps the shared memory in the guest

View File

@ -18,15 +18,15 @@ namespace skyline {
state.ctx = reinterpret_cast<ThreadContext *>(state.thread->ctxMemory->kernel.address);
while (true) {
asm("yield");
if (Halt)
if (__predict_false(Halt))
break;
if (!Surface)
if (__predict_false(!Surface))
continue;
if (state.ctx->state == ThreadState::WaitKernel) {
std::lock_guard jniGd(jniMtx);
if (Halt)
if (__predict_false(Halt))
break;
if (!Surface)
if (__predict_false(!Surface))
continue;
const u16 svc = static_cast<const u16>(state.ctx->commandId);
try {
@ -40,7 +40,7 @@ namespace skyline {
throw exception("{} (SVC: 0x{:X})", e.what(), svc);
}
state.ctx->state = ThreadState::WaitRun;
} else if (state.ctx->state == ThreadState::GuestCrash) {
} else if (__predict_false(state.ctx->state == ThreadState::GuestCrash)) {
state.logger->Warn("Thread with PID {} has crashed due to signal: {}", thread, strsignal(state.ctx->commandId));
ThreadTrace();
state.ctx->state = ThreadState::WaitRun;
@ -72,11 +72,17 @@ namespace skyline {
}
void NCE::Execute() {
while (true) {
std::lock_guard guard(jniMtx);
if (Halt)
break;
state.gpu->Loop();
try {
while (true) {
std::lock_guard guard(jniMtx);
if (Halt)
break;
state.gpu->Loop();
}
} catch (const std::exception &e) {
state.logger->Error(e.what());
} catch (...) {
state.logger->Error("An unknown exception has occurred");
}
if (!Halt) {
jniMtx.lock(GroupMutex::Group::Group2);

View File

@ -19,20 +19,17 @@ namespace skyline::kernel {
}
std::shared_ptr<type::KProcess> OS::CreateProcess(u64 entry, u64 argument, size_t stackSize) {
auto *stack = static_cast<u8 *>(mmap(nullptr, stackSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS | MAP_STACK, -1, 0));
if (stack == MAP_FAILED)
throw exception("Failed to allocate stack memory");
if (mprotect(stack, PAGE_SIZE, PROT_NONE)) {
munmap(stack, stackSize);
auto stack = std::make_shared<type::KSharedMemory>(state, 0, stackSize, memory::Permission{true, true, false}, memory::MemoryStates::Reserved, MAP_NORESERVE | MAP_STACK);
stack->guest = stack->kernel;
if (mprotect(reinterpret_cast<void *>(stack->guest.address), PAGE_SIZE, PROT_NONE))
throw exception("Failed to create guard pages");
}
auto tlsMem = std::make_shared<type::KSharedMemory>(state, 0, (sizeof(ThreadContext) + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1), memory::Permission{true, true, false}, memory::MemoryStates::Reserved);
tlsMem->guest = tlsMem->kernel;
pid_t pid = clone(reinterpret_cast<int (*)(void *)>(&guest::GuestEntry), stack + stackSize, CLONE_FILES | CLONE_FS | CLONE_SETTLS | SIGCHLD, reinterpret_cast<void *>(entry), nullptr, reinterpret_cast<void *>(tlsMem->guest.address));
pid_t pid = clone(reinterpret_cast<int (*)(void *)>(&guest::GuestEntry), reinterpret_cast<void *>(stack->guest.address + stackSize), CLONE_FILES | CLONE_FS | CLONE_SETTLS | SIGCHLD, reinterpret_cast<void *>(entry), nullptr, reinterpret_cast<void *>(tlsMem->guest.address));
if (pid == -1)
throw exception("Call to clone() has failed: {}", strerror(errno));
state.logger->Debug("Successfully created process with PID: {}", pid);
process = std::make_shared<kernel::type::KProcess>(state, pid, argument, reinterpret_cast<u64>(stack), stackSize, tlsMem);
process = std::make_shared<kernel::type::KProcess>(state, pid, argument, stack, tlsMem);
return process;
}

View File

@ -8,7 +8,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.0'
classpath 'com.android.tools.build:gradle:3.6.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong