62 lines · c
1//===---------- x86_64-specific implementations for pkey_{get,set}. -------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_SYS_MMAN_LINUX_X86_64_PKEY_COMMON_H_10#define LLVM_SYS_MMAN_LINUX_X86_64_PKEY_COMMON_H_11 12#include <immintrin.h>13 14#include "hdr/errno_macros.h" // For ENOSYS15#include "hdr/stdint_proxy.h"16#include "src/__support/common.h"17#include "src/__support/error_or.h"18 19#if !defined(LIBC_TARGET_ARCH_IS_X86_64)20#error "Invalid include"21#endif22 23namespace LIBC_NAMESPACE_DECL {24namespace pkey_common {25 26constexpr int KEY_COUNT = 16;27constexpr int KEY_MASK = 0x3;28constexpr int BITS_PER_KEY = 2;29 30// x86_64 implementation of pkey_get.31// Returns the access rights for the given pkey on success, errno otherwise.32[[gnu::target("pku")]]33LIBC_INLINE ErrorOr<int> pkey_get(int pkey) {34 if (pkey < 0 || pkey >= KEY_COUNT) {35 return Error(EINVAL);36 }37 38 uint32_t pkru = _rdpkru_u32();39 return (pkru >> (pkey * BITS_PER_KEY)) & KEY_MASK;40}41 42// x86_64 implementation of pkey_set.43// Returns 0 on success, errno otherwise.44[[gnu::target("pku")]]45LIBC_INLINE ErrorOr<int> pkey_set(int pkey, unsigned int access_rights) {46 if (pkey < 0 || pkey >= KEY_COUNT || access_rights > KEY_MASK) {47 return Error(EINVAL);48 }49 50 uint32_t pkru = _rdpkru_u32();51 pkru &= ~(KEY_MASK << (pkey * BITS_PER_KEY));52 pkru |= ((access_rights & KEY_MASK) << (pkey * BITS_PER_KEY));53 _wrpkru(pkru);54 55 return 0;56}57 58} // namespace pkey_common59} // namespace LIBC_NAMESPACE_DECL60 61#endif // LLVM_SYS_MMAN_LINUX_X86_64_PKEY_COMMON_H_62