blob: 677ce4f9c664a1fcea8b539d6ea0b2e01812c42c [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/zx/bti.h>
#include <lib/zx/iommu.h>
#include <lib/zx/msi.h>
#include <lib/zx/resource.h>
#include <lib/zx/thread.h>
#include <zircon/syscalls/iommu.h>
#include <zxtest/zxtest.h>
namespace {
extern "C" zx_handle_t get_root_resource(void);
class RootResourceFixture : public zxtest::Test {
public:
void SetUp() override {
zx_iommu_desc_dummy_t desc = {};
root_resource_ = zx::unowned_resource(get_root_resource());
ASSERT_OK(
zx::iommu::create(*root_resource_, ZX_IOMMU_TYPE_DUMMY, &desc, sizeof(desc), &iommu_));
ASSERT_OK(zx::bti::create(iommu_, 0, 0xdeadbeef, &bti_));
}
bool MsiTestsSupported() {
zx::msi msi;
return !(zx::msi::allocate(*root_resource_, 1, &msi) == ZX_ERR_NOT_SUPPORTED);
}
protected:
zx::unowned_resource root_resource_;
zx::iommu iommu_;
zx::bti bti_;
};
// This is not really a function, but an entry point for a thread that has
// a tiny stack and no other setup. It's not really entered with the C ABI
// as such. Rather, it's entered with the first argument register set to
// zx_handle_t and with the SP at the very top of the allocated stack.
// It's defined in pure assembly so that there are no issues with
// compiler-generated code's assumptions about the proper ABI setup,
// instrumentation, etc.
extern "C" void ThreadEntry(uintptr_t arg1, uintptr_t arg2);
// if (zx_interrupt_wait(static_cast<zx_handle_t>(arg1), nullptr) == ZX_OK) {
// zx_thread_exit();
// }
// ASSERT(false);
__asm__(
".pushsection .text.ThreadEntry,\"ax\",%progbits\n"
".balign 4\n"
".type ThreadEntry,%function\n"
"ThreadEntry:\n"
#ifdef __aarch64__
" mov w20, w0\n" // Save handle in callee-saves register.
" mov w0, w20\n" // Load saved handle into argument register.
" mov x1, xzr\n" // Load nullptr into argument register.
" bl zx_interrupt_wait\n" // Call.
" cbz w0, exit\n" // Exit if returned ZX_OK.
" brk #0\n" // Else crash.
"exit:\n"
" bl zx_thread_exit\n"
" brk #0\n" // Crash if we didn't exit.
#elif defined(__x86_64__)
" mov %edi, %ebx\n" // Save handle in callee-saves register.
" mov %ebx, %edi\n" // Load saved handle into argument register.
" xor %edx, %edx\n" // Load nullptr into argument register.
" call zx_interrupt_wait\n" // Call.
" testl %eax, %eax\n" // If returned ZX_OK...
" jz exit\n" // ...exit.
" ud2\n" // Else crash.
"exit:\n"
" call zx_thread_exit\n"
" ud2\n" // Crash if we didn't exit.
#else
#error "what machine?"
#endif
".size ThreadEntry, . - ThreadEntry\n"
".popsection");
} // namespace