You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kernel_samsung_sm7125/include/soc/qcom/secure_buffer.h

132 lines
3.4 KiB

/*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __QCOM_SECURE_BUFFER_H__
#define __QCOM_SECURE_BUFFER_H__
#include <linux/scatterlist.h>
/*
* if you add a secure VMID here make sure you update
* msm_secure_vmid_to_string.
* Make sure to keep the VMID_LAST as the last entry in the enum.
* This is needed in ion to create a list and it's sized using VMID_LAST.
*/
enum vmid {
VMID_HLOS = 0x3,
VMID_CP_TOUCH = 0x8,
VMID_CP_BITSTREAM = 0x9,
VMID_CP_PIXEL = 0xA,
VMID_CP_NON_PIXEL = 0xB,
VMID_CP_CAMERA = 0xD,
VMID_HLOS_FREE = 0xE,
VMID_MSS_MSA = 0xF,
VMID_MSS_NONMSA = 0x10,
VMID_CP_SEC_DISPLAY = 0x11,
VMID_CP_APP = 0x12,
VMID_WLAN = 0x18,
VMID_WLAN_CE = 0x19,
VMID_CP_SPSS_SP = 0x1A,
VMID_CP_CAMERA_PREVIEW = 0x1D,
VMID_CP_SPSS_SP_SHARED = 0x22,
VMID_CP_SPSS_HLOS_SHARED = 0x24,
VMID_CP_CAMERA_ENCODE = 0x29,
VMID_CP_CDSP = 0x2A,
VMID_CP_DSP_EXT = 0x2E,
VMID_NAV = 0x2B,
VMID_LAST = 0x2F,
VMID_INVAL = -1
};
#define PERM_READ 0x4
#define PERM_WRITE 0x2
#define PERM_EXEC 0x1
#ifdef CONFIG_QCOM_SECURE_BUFFER
int msm_secure_table(struct sg_table *table);
int msm_unsecure_table(struct sg_table *table);
int hyp_assign_table(struct sg_table *table,
u32 *source_vm_list, int source_nelems,
int *dest_vmids, int *dest_perms,
int dest_nelems);
ion: Ensure ION system secure heap shrinker doesn't deadlock When the ION system secure heap shrinker runs it attempts to free secure ION page pool pages back to the system. It does this by first HYP assigning these pages back to the system via the hyp_assign_table call. However it is possible that the shrinker was called as a result of somebody else calling hyp_assign_table, this is bad because the hyp_assign_table call holds the secure_buffer_mutex mutex so when the ION system secure heap shrinker recursively calls into hyp_assign_table it will attempt to take the secure_buffer_mutex mutex and the system will deadlock. Example of deadlock callstack -001|__schedule() -002|schedule() -003|schedule_preempt_disabled() -004|__mutex_lock_common() -005|__mutex_lock() -006|__mutex_lock_slowpath() -007|__cmpxchg_acq(inline) -007|__mutex_trylock_fast(inline) -007|mutex_lock() -008|get_info_list_from_table(inline) -008|hyp_assign_table() -009|ion_hyp_unassign_sg() -010|sg_set_page(inline) -010|ion_secure_page_pool_shrink() -011|ion_system_heap_shrink() -012|ion_system_secure_heap_shrink() -013|ion_heap_shrink_scan() -014|shrink_slab() -015|shrink_node() -016|do_try_to_free_pages() -017|__read_once_size(inline) -017|static_key_count(inline) -017|static_key_false(inline) -017|trace_mm_vmscan_direct_reclaim_end(inline) -017|try_to_free_pages() -018|memalloc_noreclaim_restore(inline) -018|__perform_reclaim(inline) -018|__alloc_pages_direct_reclaim(inline) -018|__alloc_pages_slowpath(inline) -018|__alloc_pages_nodemask() -019|__alloc_pages(inline) -019|__alloc_pages_node(inline) -019|alloc_slab_page(inline) -019|allocate_slab(inline) -019|new_slab() -020|___slab_alloc() -021|__slab_alloc(inline) -021|slab_alloc_node(inline) -021|slab_alloc(inline) -021|__kmalloc() -022|allocate_extra_arg_buffer() -023|__scm_call2() -024|scm_call2() -025|hyp_assign_table() -026|kcalloc(inline) -026|ion_hyp_assign_sg() -027|ion_system_secure_heap_prefetch_work() -028|__read_once_size(inline) -028|static_key_count(inline) -028|static_key_false(inline) -028|trace_workqueue_execute_end(inline) -028|process_one_work() -029|__read_once_size(inline) -029|list_empty(inline) -029|worker_thread() -030|kthread() -031|ret_from_fork(asm) ---|end of frame To prevent this deadlock from happening ensure that the ION system secure heap shrinker only tries to acquire he secure_buffer_mutex mutex with a try_lock call. Change-Id: I0e108b181ba36c57c382517d5916131f9c9b92eb Signed-off-by: Liam Mark <lmark@codeaurora.org>
6 years ago
int try_hyp_assign_table(struct sg_table *table,
u32 *source_vm_list, int source_nelems,
int *dest_vmids, int *dest_perms,
int dest_nelems);
extern int hyp_assign_phys(phys_addr_t addr, u64 size,
u32 *source_vmlist, int source_nelems,
int *dest_vmids, int *dest_perms, int dest_nelems);
extern int cma_hyp_assign_phys(struct device *dev, u32 *source_vm_list,
int source_nelems, int *dest_vmids,
int *dest_perms, int dest_nelems);
bool msm_secure_v2_is_supported(void);
const char *msm_secure_vmid_to_string(int secure_vmid);
#else
static inline int msm_secure_table(struct sg_table *table)
{
return -EINVAL;
}
static inline int msm_unsecure_table(struct sg_table *table)
{
return -EINVAL;
}
static inline int hyp_assign_table(struct sg_table *table,
u32 *source_vm_list, int source_nelems,
int *dest_vmids, int *dest_perms,
int dest_nelems)
{
return -EINVAL;
}
ion: Ensure ION system secure heap shrinker doesn't deadlock When the ION system secure heap shrinker runs it attempts to free secure ION page pool pages back to the system. It does this by first HYP assigning these pages back to the system via the hyp_assign_table call. However it is possible that the shrinker was called as a result of somebody else calling hyp_assign_table, this is bad because the hyp_assign_table call holds the secure_buffer_mutex mutex so when the ION system secure heap shrinker recursively calls into hyp_assign_table it will attempt to take the secure_buffer_mutex mutex and the system will deadlock. Example of deadlock callstack -001|__schedule() -002|schedule() -003|schedule_preempt_disabled() -004|__mutex_lock_common() -005|__mutex_lock() -006|__mutex_lock_slowpath() -007|__cmpxchg_acq(inline) -007|__mutex_trylock_fast(inline) -007|mutex_lock() -008|get_info_list_from_table(inline) -008|hyp_assign_table() -009|ion_hyp_unassign_sg() -010|sg_set_page(inline) -010|ion_secure_page_pool_shrink() -011|ion_system_heap_shrink() -012|ion_system_secure_heap_shrink() -013|ion_heap_shrink_scan() -014|shrink_slab() -015|shrink_node() -016|do_try_to_free_pages() -017|__read_once_size(inline) -017|static_key_count(inline) -017|static_key_false(inline) -017|trace_mm_vmscan_direct_reclaim_end(inline) -017|try_to_free_pages() -018|memalloc_noreclaim_restore(inline) -018|__perform_reclaim(inline) -018|__alloc_pages_direct_reclaim(inline) -018|__alloc_pages_slowpath(inline) -018|__alloc_pages_nodemask() -019|__alloc_pages(inline) -019|__alloc_pages_node(inline) -019|alloc_slab_page(inline) -019|allocate_slab(inline) -019|new_slab() -020|___slab_alloc() -021|__slab_alloc(inline) -021|slab_alloc_node(inline) -021|slab_alloc(inline) -021|__kmalloc() -022|allocate_extra_arg_buffer() -023|__scm_call2() -024|scm_call2() -025|hyp_assign_table() -026|kcalloc(inline) -026|ion_hyp_assign_sg() -027|ion_system_secure_heap_prefetch_work() -028|__read_once_size(inline) -028|static_key_count(inline) -028|static_key_false(inline) -028|trace_workqueue_execute_end(inline) -028|process_one_work() -029|__read_once_size(inline) -029|list_empty(inline) -029|worker_thread() -030|kthread() -031|ret_from_fork(asm) ---|end of frame To prevent this deadlock from happening ensure that the ION system secure heap shrinker only tries to acquire he secure_buffer_mutex mutex with a try_lock call. Change-Id: I0e108b181ba36c57c382517d5916131f9c9b92eb Signed-off-by: Liam Mark <lmark@codeaurora.org>
6 years ago
static inline int try_hyp_assign_table(struct sg_table *table,
u32 *source_vm_list, int source_nelems,
int *dest_vmids, int *dest_perms,
int dest_nelems)
{
return -EINVAL;
}
static inline int hyp_assign_phys(phys_addr_t addr, u64 size,
u32 *source_vmlist, int source_nelems,
int *dest_vmids, int *dest_perms, int dest_nelems)
{
return -EINVAL;
}
static inline int cma_hyp_assign_phys(struct device *dev, u32 *source_vm_list,
int source_nelems, int *dest_vmids,
int *dest_perms, int dest_nelems)
{
return -EINVAL;
}
static inline bool msm_secure_v2_is_supported(void)
{
return false;
}
static inline const char *msm_secure_vmid_to_string(int secure_vmid)
{
return "N/A";
}
#endif
#endif