Skip to content
2 changes: 2 additions & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2374,3 +2374,5 @@ source "drivers/acpi/Kconfig"

source "arch/arm64/kvm/Kconfig"

source "arch/arm64/kernel/haoc/Kconfig"

1 change: 1 addition & 0 deletions arch/arm64/configs/deepin_arm64_desktop_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ CONFIG_ACPI_FFH=y
CONFIG_PMIC_OPREGION=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=y
CONFIG_IEE=y
CONFIG_KPROBES=y
CONFIG_SHADOW_CALL_STACK=y
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

需要删掉CONFIG_SHADOW_CALL_STACK=y?

CONFIG_MODULES=y
Expand Down
26 changes: 26 additions & 0 deletions arch/arm64/include/asm/haoc/haoc-def.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* HAOC feature support
*
* Copyright (C) 2025 ZGCLAB
* Authors: Lyu Jinglin <[email protected]>
* Zhang Shiyang <[email protected]>
*/

#ifndef _LINUX_HAOC_DEF_H
#define _LINUX_HAOC_DEF_H

/* Place the enum entries in the order corresponding to iee_funcs array. */
enum {
IEE_OP_MEMSET,
IEE_FLAG_END
};

/* The entry gate of all IEE APIs. The first parameter must be a valid
* IEE function index.
*/
extern unsigned long long iee_rw_gate(int flag, ...);

#define __iee_code __section(".iee.text")

#endif
18 changes: 18 additions & 0 deletions arch/arm64/include/asm/haoc/haoc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* HAOC feature support
*
* Copyright (C) 2025 ZGCLAB
* Authors: Lyu Jinglin <[email protected]>
* Zhang Shiyang <[email protected]>
*/

#ifndef _LINUX_HAOC_H
#define _LINUX_HAOC_H

#include <linux/types.h>
#include <linux/mm.h>

void _iee_memset(unsigned long __unused, void *ptr, int data, size_t n);

#endif
25 changes: 25 additions & 0 deletions arch/arm64/include/asm/haoc/iee-access.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* HAOC feature support
*
* Copyright (C) 2025 ZGCLAB
* Authors: Lyu Jinglin <[email protected]>
* Zhang Shiyang <[email protected]>
*/

#ifndef _LINUX_IEE_ACCESS_H
#define _LINUX_IEE_ACCESS_H

#include <asm/haoc/haoc-def.h>
#include <asm/haoc/iee.h>

/* An example of IEE API. */
static inline void iee_memset(void *ptr, int data, size_t n)
{
if (haoc_enabled)
iee_rw_gate(IEE_OP_MEMSET, ptr, data, n);
else
memset(ptr, data, n);
}

#endif
35 changes: 35 additions & 0 deletions arch/arm64/include/asm/haoc/iee-asm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* HAOC feature support
*
* Copyright (C) 2025 ZGCLAB
* Authors: Lyu Jinglin <[email protected]>
* Zhang Shiyang <[email protected]>
*/

#ifndef _LINUX_IEE_ASM_H
#define _LINUX_IEE_ASM_H

#include <asm/pgtable-hwdef.h>

#define BAD_ELR_EL1 0
#define BAD_TCR_EL1 1

#define ASID_BIT (UL(1) << 48)
/*
* We reserves the bigest ASID for IEE and always stores it in TTBR1. As KPTI also reserves
* odd ASIDs for user-viewed TTBR1, we should use even number for IEE ASID to allow KPTI to
* switch between them at kernel entry/exit.
*/
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
#define IEE_ASID 0xfffe
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里ASID的使用加注释说明

#else
#define IEE_ASID 0xffff
#endif
#define IEE_ASM_ASID (UL(IEE_ASID) << 48)

#define TCR_HPD1 (UL(1) << 42)
#define TCR_A1 (UL(1) << 22)
#define IEE_TCR_MASK (~(TCR_HD | TCR_E0PD1 | TCR_T0SZ_MASK))

#endif
17 changes: 17 additions & 0 deletions arch/arm64/include/asm/haoc/iee-func.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* HAOC feature support
*
* Copyright (C) 2025 ZGCLAB
* Authors: Lyu Jinglin <[email protected]>
* Zhang Shiyang <[email protected]>
*/

#ifndef _LINUX_IEE_ASM_FUNC_H
#define _LINUX_IEE_ASM_FUNC_H

extern void put_pages_into_iee(unsigned long addr, int order);
extern void set_iee_page(unsigned long addr, int order);
extern void unset_iee_page(unsigned long addr, int order);

#endif
20 changes: 20 additions & 0 deletions arch/arm64/include/asm/haoc/iee-init.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* HAOC feature support
*
* Copyright (C) 2025 ZGCLAB
* Authors: Lyu Jinglin <[email protected]>
* Zhang Shiyang <[email protected]>
*/

#ifndef _LINUX_IEE_INIT_H
#define _LINUX_IEE_INIT_H

#define NO_BLOCK_MAPPINGS BIT(0)
#define NO_CONT_MAPPINGS BIT(1)
#define NO_EXEC_MAPPINGS BIT(2) /* assumes FEAT_HPDS is not used */

extern char iee_init_data_begin[];
extern char iee_init_data_end[];

#endif
23 changes: 23 additions & 0 deletions arch/arm64/include/asm/haoc/iee-mmu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* HAOC feature support
*
* Copyright (C) 2025 ZGCLAB
* Authors: Lyu Jinglin <[email protected]>
* Zhang Shiyang <[email protected]>
*/

#ifndef _LINUX_IEE_MMU_H
#define _LINUX_IEE_MMU_H

extern phys_addr_t __init early_iee_stack_alloc(int order);
extern void __iee_create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
unsigned long virt, phys_addr_t size,
pgprot_t prot,
phys_addr_t (*pgtable_alloc)(int),
int flags);
extern void __init iee_init_mappings(pgd_t *pgdp);
extern void __init init_early_iee_data(void);
extern void __init early_iee_data_cache_init(void);

#endif
76 changes: 76 additions & 0 deletions arch/arm64/include/asm/haoc/iee.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* HAOC feature support
*
* Copyright (C) 2025 ZGCLAB
* Authors: Lyu Jinglin <[email protected]>
* Zhang Shiyang <[email protected]>
*/

#ifndef _LINUX_IEE_H
#define _LINUX_IEE_H

#include <linux/mm.h>
#include <linux/types.h>
#include <asm/haoc/iee-func.h>

extern unsigned long iee_tcr;
extern unsigned long kernel_tcr;
extern bool iee_init_done;
extern bool haoc_enabled;

#define IEE_OFFSET 0x400000000000
#define IEE_DATA_ORDER (PMD_SHIFT - PAGE_SHIFT)

#define __phys_to_iee(x) (__phys_to_virt(x) | IEE_OFFSET)
#define __virt_to_iee(x) (((u64)x) | IEE_OFFSET)
#define __kimg_to_iee(x) (__phys_to_iee(__pa_symbol(x)))
#define __page_to_iee(x) (__phys_to_iee(page_to_phys(x)))

#define __iee_to_virt(x) (((u64)x) & ~IEE_OFFSET)
#define __iee_to_phys(x) (__pa(__iee_to_virt(x)))

/* Support conversion from both kernel and linear addresses. */
#define __ptr_to_iee(x) ({ \
typeof(x) __val; \
if (__is_lm_address((u64)x)) \
__val = ((typeof(x))(__virt_to_iee((u64)x))); \
else \
__val = ((typeof(x))(__kimg_to_iee((u64)x))); \
__val; \
})

#define SET_UPAGE(x) __pgprot(pgprot_val(x) | PTE_USER)
#define SET_PPAGE(x) __pgprot(pgprot_val(x) & (~PTE_USER))
#define SET_INVALID(x) __pgprot(pgprot_val(x) & (~PTE_VALID))
#define SET_NG(x) __pgprot(pgprot_val(x) | PTE_NG)
/*
* The APTable and XNTable bits in ARM64 table descriptors play a critical role in hierarchical
* permission systems, where higher-level permissions restrict lower-level entries, and we may
* change the page permission by enable/disable hierarchical permission with supprot of FEAT_HPDS.
*/
#define PGD_APTABLE_RO (_AT(pudval_t, 1) << 62)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

加一下注释说明用法

#define PGD_APTABLE (_AT(pudval_t, 1) << 61)
#define PGD_PXNTABLE (_AT(pudval_t, 1) << 59)
#define PGD_UXNTABLE (_AT(pudval_t, 1) << 60)

#define TCR_HPD1 (UL(1) << 42)

void iee_init_mappings(pgd_t *pgdp);
void iee_init_post(void);
void iee_stack_init(void);
void iee_init_tcr(void);
void iee_setup_asid(void);

#define IEE_STACK_ORDER 0x3
#define IEE_STACK_SIZE (PAGE_SIZE << IEE_STACK_ORDER)

#define IEE_CHECK(condition) do { \
if (unlikely(condition)) \
panic("IEE check failed on %s.", __func__); \
} while (0)

extern void arm64_enter_nmi(struct pt_regs *regs);
extern const char *esr_get_class_string(unsigned long esr);

#endif
1 change: 1 addition & 0 deletions arch/arm64/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ obj-y := debug-monitors.o entry.o irq.o fpsimd.o \
syscall.o proton-pack.o idreg-override.o idle.o \
patching.o

obj-$(CONFIG_IEE) += haoc/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

请对齐缩进。

obj-$(CONFIG_COMPAT) += sys32.o signal32.o \
sys_compat.o
obj-$(CONFIG_COMPAT) += sigreturn32.o
Expand Down
4 changes: 4 additions & 0 deletions arch/arm64/kernel/entry-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@ asmlinkage void noinstr asm_exit_to_user_mode(struct pt_regs *regs)
* mode. Before this function is called it is not safe to call regular kernel
* code, instrumentable code, or any code which may trigger an exception.
*/
#ifdef CONFIG_IEE
void noinstr arm64_enter_nmi(struct pt_regs *regs)
#else
static void noinstr arm64_enter_nmi(struct pt_regs *regs)
#endif
{
regs->lockdep_hardirqs = lockdep_hardirqs_enabled();

Expand Down
26 changes: 26 additions & 0 deletions arch/arm64/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,29 @@
#include <asm/thread_info.h>
#include <asm/asm-uaccess.h>
#include <asm/unistd.h>
#ifdef CONFIG_IEE
#include <asm/haoc/iee-asm.h>
#endif

#ifdef CONFIG_IEE
/* IEE code shall not be interrupted. */
.macro iee_elr_check
ldr x1, =__iee_code_start
cmp x1, x22 /* ELR_EL1 was stored in x22 on kernel entry. */
b.hi 114f
ldr x2, =__iee_code_end
cmp x2, x22
b.lo 114f
/* ELR check fail */
mov x0, sp
mov x1, #BAD_ELR_EL1
mrs x2, esr_el1
mov x3, x22
bl iee_bad_mode
ASM_BUG()
114:
.endm
#endif

.macro clear_gp_regs
.irp n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29
Expand Down Expand Up @@ -573,6 +596,9 @@ SYM_CODE_END(__bad_stack)
.macro entry_handler el:req, ht:req, regsize:req, label:req
SYM_CODE_START_LOCAL(el\el\ht\()_\regsize\()_\label)
kernel_entry \el, \regsize
#ifdef CONFIG_IEE
iee_elr_check
#endif
mov x0, sp
bl el\el\ht\()_\regsize\()_\label\()_handler
.if \el == 0
Expand Down
17 changes: 17 additions & 0 deletions arch/arm64/kernel/haoc/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SPDX-License-Identifier: GPL-2.0
#
# Hardware assisted os compartmentalization(Haoc) configuration
#
menu "Hardware Assisted OS Compartmentalization(HAOC)"

config IEE
bool "Isolated Execution Environment Framework(IEE)"
depends on ARM64_4K_PAGES
depends on ARM64_VA_BITS_48
help
Support for Isolated Execution Environment Framework. Foundation of HAOC.
Could isolate kernel critical data and enforce all write access made and
verified in IEE APIs.
Needs hardware support FEAT_HPDS.

endmenu # HAOC
3 changes: 3 additions & 0 deletions arch/arm64/kernel/haoc/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += haoc.o
obj-y += iee/
24 changes: 24 additions & 0 deletions arch/arm64/kernel/haoc/haoc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-2.0
/*
* HAOC feature support
*
* Copyright (C) 2025 ZGCLAB
* Authors: Lyu Jinglin <[email protected]>
* Zhang Shiyang <[email protected]>
*/

#include <asm/haoc/haoc.h>

typedef void (*iee_func)(void);

/*
* Register IEE handler functions here.
* IEE gate would find out the specific handler function inside this array
* using the index that iee_rw_gate() gives, so the arrangement of these
* IEE functions should correspond one-to-one with the enum entries in haoc-def.h,
* such as IEE_OP_MEMSET to call _iee_memset().
*/
iee_func iee_funcs[] = {
(iee_func)_iee_memset,
NULL
};
2 changes: 2 additions & 0 deletions arch/arm64/kernel/haoc/iee/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_IEE) += iee.o iee-gate.o iee-init.o iee-func.o iee-mmu.o
Loading
Loading