Skip to content

Commit

Permalink
Fix GitHub Actions Build + Move Stack to Shared Memory
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
PixelyIon committed Apr 23, 2020
1 parent 38f63ec commit 5f072da
Show file tree
Hide file tree
Showing 11 changed files with 1,585 additions and 33 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 0 additions & 3 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1,530 changes: 1,528 additions & 2 deletions .idea/inspectionProfiles/Project_Default.xml

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions .idea/jsonSchemas.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions app/src/main/cpp/skyline/kernel/types/KProcess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/cpp/skyline/kernel/types/KProcess.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/cpp/skyline/kernel/types/KSharedMemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
26 changes: 16 additions & 10 deletions app/src/main/cpp/skyline/nce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
13 changes: 5 additions & 8 deletions app/src/main/cpp/skyline/os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 5f072da

Please sign in to comment.