162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include <linux/export.h>
462306a36Sopenharmony_ci#include <linux/mm.h>
562306a36Sopenharmony_ci#include <asm/pgtable.h>
662306a36Sopenharmony_ci#include <asm/mem_encrypt.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_cistatic pgprot_t protection_map[16] __ro_after_init = {
962306a36Sopenharmony_ci	[VM_NONE]					= PAGE_NONE,
1062306a36Sopenharmony_ci	[VM_READ]					= PAGE_READONLY,
1162306a36Sopenharmony_ci	[VM_WRITE]					= PAGE_COPY,
1262306a36Sopenharmony_ci	[VM_WRITE | VM_READ]				= PAGE_COPY,
1362306a36Sopenharmony_ci	[VM_EXEC]					= PAGE_READONLY_EXEC,
1462306a36Sopenharmony_ci	[VM_EXEC | VM_READ]				= PAGE_READONLY_EXEC,
1562306a36Sopenharmony_ci	[VM_EXEC | VM_WRITE]				= PAGE_COPY_EXEC,
1662306a36Sopenharmony_ci	[VM_EXEC | VM_WRITE | VM_READ]			= PAGE_COPY_EXEC,
1762306a36Sopenharmony_ci	[VM_SHARED]					= PAGE_NONE,
1862306a36Sopenharmony_ci	[VM_SHARED | VM_READ]				= PAGE_READONLY,
1962306a36Sopenharmony_ci	[VM_SHARED | VM_WRITE]				= PAGE_SHARED,
2062306a36Sopenharmony_ci	[VM_SHARED | VM_WRITE | VM_READ]		= PAGE_SHARED,
2162306a36Sopenharmony_ci	[VM_SHARED | VM_EXEC]				= PAGE_READONLY_EXEC,
2262306a36Sopenharmony_ci	[VM_SHARED | VM_EXEC | VM_READ]			= PAGE_READONLY_EXEC,
2362306a36Sopenharmony_ci	[VM_SHARED | VM_EXEC | VM_WRITE]		= PAGE_SHARED_EXEC,
2462306a36Sopenharmony_ci	[VM_SHARED | VM_EXEC | VM_WRITE | VM_READ]	= PAGE_SHARED_EXEC
2562306a36Sopenharmony_ci};
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_civoid add_encrypt_protection_map(void)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	unsigned int i;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
3262306a36Sopenharmony_ci		protection_map[i] = pgprot_encrypted(protection_map[i]);
3362306a36Sopenharmony_ci}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cipgprot_t vm_get_page_prot(unsigned long vm_flags)
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci	unsigned long val = pgprot_val(protection_map[vm_flags &
3862306a36Sopenharmony_ci				      (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]);
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
4162306a36Sopenharmony_ci	/*
4262306a36Sopenharmony_ci	 * Take the 4 protection key bits out of the vma->vm_flags value and
4362306a36Sopenharmony_ci	 * turn them in to the bits that we can put in to a pte.
4462306a36Sopenharmony_ci	 *
4562306a36Sopenharmony_ci	 * Only override these if Protection Keys are available (which is only
4662306a36Sopenharmony_ci	 * on 64-bit).
4762306a36Sopenharmony_ci	 */
4862306a36Sopenharmony_ci	if (vm_flags & VM_PKEY_BIT0)
4962306a36Sopenharmony_ci		val |= _PAGE_PKEY_BIT0;
5062306a36Sopenharmony_ci	if (vm_flags & VM_PKEY_BIT1)
5162306a36Sopenharmony_ci		val |= _PAGE_PKEY_BIT1;
5262306a36Sopenharmony_ci	if (vm_flags & VM_PKEY_BIT2)
5362306a36Sopenharmony_ci		val |= _PAGE_PKEY_BIT2;
5462306a36Sopenharmony_ci	if (vm_flags & VM_PKEY_BIT3)
5562306a36Sopenharmony_ci		val |= _PAGE_PKEY_BIT3;
5662306a36Sopenharmony_ci#endif
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	val = __sme_set(val);
5962306a36Sopenharmony_ci	if (val & _PAGE_PRESENT)
6062306a36Sopenharmony_ci		val &= __supported_pte_mask;
6162306a36Sopenharmony_ci	return __pgprot(val);
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ciEXPORT_SYMBOL(vm_get_page_prot);
64