Commit caaefd56 authored by Jingxian He's avatar Jingxian He Committed by hejingxian
Browse files

mm: enable swiotlb alloc for cvm share mem

virtcca inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IAGYKI



--------------------------------

Enable swiotlb alloc for cvm share mem:
1. Cvm guest mapped memory is secure memory.
2. Qemu/kvm cannot access the secure memory.
3. Use swiotlb buffer as memory shared by cvm guest and qemu/kvm.

Signed-off-by: default avatarJingxian He <hejingxian@huawei.com>
parent 1182be89
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -2576,6 +2576,14 @@ config COMPAT
	def_bool y
	depends on AARCH32_EL0 || ARM64_ILP32

config HISI_VIRTCCA_GUEST
	bool "Enable cvm guest run"
	depends on DMA_RESTRICTED_POOL
	help
	  Support VIRTCCA CVM guest based on S-EL2

	  If unsure, say N.

menu "Power management options"

source "kernel/power/Kconfig"
+1 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
#define _ASM_ARM64_SET_MEMORY_H

#include <asm-generic/set_memory.h>
#include <asm/virtcca_cvm_guest.h>

bool can_set_direct_map(void);
#define can_set_direct_map can_set_direct_map
+39 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2024. Huawei Technologies Co., Ltd. All rights reserved.
 */
#ifndef __VIRTCCA_CVM_GUEST_H
#define __VIRTCCA_CVM_GUEST_H

#ifdef CONFIG_HISI_VIRTCCA_GUEST
struct device;

extern int set_cvm_memory_encrypted(unsigned long addr, int numpages);

extern int set_cvm_memory_decrypted(unsigned long addr, int numpages);

extern bool is_virtcca_cvm_world(void);

extern void __init swiotlb_cvm_update_mem_attributes(void);

#else

static inline int set_cvm_memory_encrypted(unsigned long addr, int numpages)
{
	return 0;
}

static inline int set_cvm_memory_decrypted(unsigned long addr, int numpages)
{
	return 0;
}

static inline bool is_virtcca_cvm_world(void)
{
	return false;
}

static inline void __init swiotlb_cvm_update_mem_attributes(void) {}

#endif /* CONFIG_HISI_VIRTCCA_GUEST */
#endif /* __VIRTCCA_CVM_GUEST_H */
+1 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ obj-$(CONFIG_COMPAT_VDSO) += vdso32-wrap.o
obj-$(CONFIG_ARM64_ILP32)		+= vdso-ilp32/
obj-$(CONFIG_UNWIND_PATCH_PAC_INTO_SCS)	+= patch-scs.o
obj-$(CONFIG_IPI_AS_NMI)		+= ipi_nmi.o
obj-$(CONFIG_HISI_VIRTCCA_GUEST)	+= virtcca_cvm_guest.o
CFLAGS_patch-scs.o			+= -mbranch-protection=none

# Force dependency (vdso*-wrap.S includes vdso.so through incbin)
+93 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2024. Huawei Technologies Co., Ltd. All rights reserved.
 */
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>

#include <asm/cacheflush.h>
#include <asm/set_memory.h>
#include <asm/tlbflush.h>

#define CVM_PTE_NS_BIT   5
#define CVM_PTE_NS_MASK  (1 << CVM_PTE_NS_BIT)

static bool cvm_guest_enable __read_mostly;

/* please use 'virtcca_cvm_guest=1' to enable cvm guest feature */
static int __init setup_cvm_guest(char *str)
{
	int ret;
	unsigned int val;

	if (!str)
		return 0;

	ret = kstrtouint(str, 10, &val);
	if (ret) {
		pr_warn("Unable to parse cvm_guest.\n");
	} else {
		if (val)
			cvm_guest_enable = true;
	}
	return ret;
}
early_param("virtcca_cvm_guest", setup_cvm_guest);

bool is_virtcca_cvm_world(void)
{
	return cvm_guest_enable;
}

static int change_page_range_cvm(pte_t *ptep, unsigned long addr, void *data)
{
	bool encrypt = (bool)data;
	pte_t pte = READ_ONCE(*ptep);

	if (encrypt) {
		if (!(pte.pte & CVM_PTE_NS_MASK))
			return 0;
		pte.pte = pte.pte & (~CVM_PTE_NS_MASK);
	} else {
		if (pte.pte & CVM_PTE_NS_MASK)
			return 0;
		/* Set NS BIT */
		pte.pte = pte.pte | CVM_PTE_NS_MASK;
	}
	set_pte(ptep, pte);

	return 0;
}

static int __change_memory_common_cvm(unsigned long start, unsigned long size, bool encrypt)
{
	int ret;

	ret = apply_to_page_range(&init_mm, start, size, change_page_range_cvm, (void *)encrypt);
	flush_tlb_kernel_range(start, start + size);
	return ret;
}

static int __set_memory_encrypted(unsigned long addr,
			int numpages,
			bool encrypt)
{
	if (!is_virtcca_cvm_world())
		return 0;

	WARN_ON(!__is_lm_address(addr));
	return __change_memory_common_cvm(addr, PAGE_SIZE * numpages, encrypt);
}

int set_cvm_memory_encrypted(unsigned long addr, int numpages)
{
	return __set_memory_encrypted(addr, numpages, true);
}

int set_cvm_memory_decrypted(unsigned long addr, int numpages)
{
	return __set_memory_encrypted(addr, numpages, false);
}
Loading