diff options
author | Sunyeal Hong <sunyeal.hong@samsung.com> | 2016-11-17 20:03:30 +0900 |
---|---|---|
committer | Sooman Jeong <sm5.jeong@samsung.com> | 2016-11-29 01:48:46 +0000 |
commit | 20a6af298d83f83f89f76712b24afff127c034e6 (patch) | |
tree | 76152cd24e3cf276d02ba37b42d0927ae0189295 | |
parent | 855f77afdc9cefec659460ec87774857632f29c3 (diff) | |
download | linux-artik7-20a6af298d83f83f89f76712b24afff127c034e6.tar.gz linux-artik7-20a6af298d83f83f89f76712b24afff127c034e6.tar.bz2 linux-artik7-20a6af298d83f83f89f76712b24afff127c034e6.zip |
misc: artiktee: release 2.23.1.8
- add support for exporting pfnmap memory.
- fixup bug in aarch64 v2p_translation.
- hide physical address in user space.
Change-Id: Iee2742de36284409f5f5043542b7771286cf1e4c
Signed-off-by: Sunyeal Hong <sunyeal.hong@samsung.com>
-rw-r--r-- | drivers/misc/artiktee/dumpdev_core.c | 8 | ||||
-rw-r--r-- | drivers/misc/artiktee/ssdev_core.c | 5 | ||||
-rw-r--r-- | drivers/misc/artiktee/ssdev_file.c | 4 | ||||
-rw-r--r-- | drivers/misc/artiktee/tzdev_internal.h | 11 | ||||
-rw-r--r-- | drivers/misc/artiktee/tzdev_main.c | 42 | ||||
-rw-r--r-- | drivers/misc/artiktee/tzdev_smc.c | 9 | ||||
-rw-r--r-- | drivers/misc/artiktee/tzdev_smc.h | 4 | ||||
-rw-r--r-- | drivers/misc/artiktee/tzlinkmgr.c | 3 | ||||
-rw-r--r-- | drivers/misc/artiktee/tzlog.c | 1 | ||||
-rw-r--r-- | drivers/misc/artiktee/tzlog_core.c | 23 | ||||
-rw-r--r-- | drivers/misc/artiktee/tzlog_core.h | 2 | ||||
-rw-r--r-- | drivers/misc/artiktee/tzlog_print.c | 4 | ||||
-rw-r--r-- | drivers/misc/artiktee/tzmem.c | 10 | ||||
-rw-r--r-- | drivers/misc/artiktee/tzsys.c | 5 | ||||
-rw-r--r-- | drivers/misc/artiktee/tzwsm.c | 212 |
15 files changed, 277 insertions, 66 deletions
diff --git a/drivers/misc/artiktee/dumpdev_core.c b/drivers/misc/artiktee/dumpdev_core.c index 091039a3be07..80e0b3f73f57 100644 --- a/drivers/misc/artiktee/dumpdev_core.c +++ b/drivers/misc/artiktee/dumpdev_core.c @@ -36,7 +36,7 @@ extern uint get_minidump_buf_size(void); /* TODO : will be remove this declare. and should be share tzsys.c's dump path */ #define ERROR_DUMP_DIR_PATH "/save_error_log/error_log/secureos_dump/" -static char* get_file_full_path(char *file_name, char *dst_buf, int dst_buf_len) +static char *get_file_full_path(char *file_name, char *dst_buf, int dst_buf_len) { if (file_name == NULL) return NULL; @@ -71,8 +71,7 @@ static int copy_to_file_from_ring( iov[i].iov_len); break; } - } - else { + } else { if (ss_file_append_object(file_full_path, iov[i].iov_base, iov[i].iov_len) != iov[i].iov_len) { @@ -87,7 +86,6 @@ static int copy_to_file_from_ring( return n_written; } - void dumpdev_handler(NSRPCTransaction_t *txn_object) { int ret = 0; @@ -100,7 +98,7 @@ void dumpdev_handler(NSRPCTransaction_t *txn_object) dumpdev_ctrl = (pss_dump_ctrl)nsrpc_payload_ptr(txn_object); ring_size = get_minidump_buf_size(); - ring = (struct chimera_ring_buffer*)get_minidump_buf(); + ring = (struct chimera_ring_buffer *)get_minidump_buf(); if (ring == NULL || ring_size == 0) { tzlog_print(K_ERR, "NSRPC: can not process : ring : %p ring_size : %d\n", ring, ring_size); diff --git a/drivers/misc/artiktee/ssdev_core.c b/drivers/misc/artiktee/ssdev_core.c index eb98f5dc0485..fa8da4754738 100644 --- a/drivers/misc/artiktee/ssdev_core.c +++ b/drivers/misc/artiktee/ssdev_core.c @@ -35,7 +35,6 @@ #include "ssdev_file.h" #include "tzdev.h" -#include "tzpage.h" #include "tzdev_internal.h" #include "tzdev_smc.h" #include "nsrpc_ree_slave.h" @@ -394,7 +393,7 @@ static void ssdev_file_create_data(NSRPCTransaction_t *tsx) int ret; int file_size; void *wsm_buffer = - (char *)ss_wsm_channel.payload + nsrpc_wsm_offset(tsx, + (char *)ss_wsm_channel.payload + nsrpc_wsm_offset(tsx, &wsm_size); ssdev_filename_create(file_main, sizeof(file_main), @@ -899,4 +898,4 @@ int libprov_handler(NSRPCTransaction_t *txn_object) return 0; } -#endif +#endif /* CONFIG_TEE_LIBRARY_PROVISION */ diff --git a/drivers/misc/artiktee/ssdev_file.c b/drivers/misc/artiktee/ssdev_file.c index 065176153aaf..dc6c5cb48601 100644 --- a/drivers/misc/artiktee/ssdev_file.c +++ b/drivers/misc/artiktee/ssdev_file.c @@ -114,6 +114,8 @@ void ss_file_delete_object(char *path) return; #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)) if (0) +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) + if (!d_is_file(file_path.dentry)) #else if (!d_is_file(file_path.dentry) || d_really_is_negative(file_path.dentry)) @@ -128,6 +130,8 @@ void ss_file_delete_object(char *path) if (!IS_ERR(dir)) { #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)) err = vfs_unlink(dir->d_inode, file_path.dentry); +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)) + err = vfs_unlink(dir->d_inode, file_path.dentry, NULL); #else err = vfs_unlink(d_inode(dir), file_path.dentry, NULL); #endif diff --git a/drivers/misc/artiktee/tzdev_internal.h b/drivers/misc/artiktee/tzdev_internal.h index 8c291014d2fb..4bd4b757e2ac 100644 --- a/drivers/misc/artiktee/tzdev_internal.h +++ b/drivers/misc/artiktee/tzdev_internal.h @@ -102,6 +102,9 @@ struct secos_kern_info { /* Secos build type */ char build_type[32]; + + /* Secos build info */ + char build_info[256]; }; #define SECOS_KERN_INFO_V1 (sizeof(struct secos_kern_info)) @@ -133,6 +136,7 @@ void tzio_release_link(struct tzio_link *link); int tzwsm_register_tzdev_memory( uint64_t ctx_id, struct page **pages, + phys_addr_t *pfns, size_t num_pages, gfp_t gfp, int for_kernel); @@ -144,8 +148,15 @@ int tzwsm_register_user_memory( int rw, gfp_t gfp, struct page ***p_pages, + phys_addr_t **p_pfns, size_t *p_num_pages); void tzwsm_unregister_kernel_memory(int wsmid); +void tzwsm_unregister_user_memory( + int wsmid, + struct page **pages, + phys_addr_t *pfns, + size_t num_pages); + #endif /* __SecureOS__ */ #endif /* __SOURCE_TZDEV_TZDEV_INTERNAL_H__ */ diff --git a/drivers/misc/artiktee/tzdev_main.c b/drivers/misc/artiktee/tzdev_main.c index 44e07877cc56..f19ea3148c1e 100644 --- a/drivers/misc/artiktee/tzdev_main.c +++ b/drivers/misc/artiktee/tzdev_main.c @@ -53,7 +53,6 @@ #include "tzdev_init.h" #include "tzdev_internal.h" #include "nsrpc_ree_slave.h" -#include "tzpage.h" #include "tzdev_smc.h" #include "tzdev_plat.h" @@ -1828,8 +1827,6 @@ static int fetch_kernel_info(void) } memcpy(&secos_kernel_info, &kinfo, sizeof(kinfo)); - if (kinfo.shmem_base && kinfo.shmem_size) - tzpage_init(kinfo.shmem_base, kinfo.shmem_size); return rc; } @@ -1843,18 +1840,25 @@ extern struct miscdevice tzrsrc; #define TZCMA_LLI_TBL_PAGE 4 #define TZCMA_ALLOC_MAX_COUNT 4 #define TZCMA_MAX_SUPPORT_SIZE SZ_4M +#define TZCMA_UNMMAPED 0 +#define TZCMA_MMAPED 1 static struct device *tzcma_dev; struct tzcma_info { int chan_id; size_t size; - dma_addr_t phyAddr; unsigned long virtAddr; }; - -static void *tzcma_cpuAddr[TZCMA_ALLOC_MAX_COUNT]; struct tzcma_info g_tzcmas[TZCMA_ALLOC_MAX_COUNT]; struct dma_chan *g_tzcma_channels[TZCMA_ALLOC_MAX_COUNT]; + +struct tzcma_info_internal { + int is_mmaped; + dma_addr_t phyAddr; + void *cpuAddr; +}; +static struct tzcma_info_internal g_tzcmas_internal[TZCMA_ALLOC_MAX_COUNT]; + int g_tzcma_alloc_cnt; bool g_tzcma_state_opened; @@ -1879,7 +1883,7 @@ static int tzcma_get_alloc_idx(void) int i; for (i = 0; i < TZCMA_ALLOC_MAX_COUNT; i++) { - if (g_tzcmas[i].phyAddr == 0) + if (g_tzcmas_internal[i].phyAddr == 0) return i; } return -1; @@ -1890,7 +1894,8 @@ static int tzcma_get_free_idx(struct tzcma_info mem) int i; for (i = 0; i < TZCMA_ALLOC_MAX_COUNT; i++) { - if (g_tzcmas[i].phyAddr == mem.phyAddr) + if (g_tzcmas[i].chan_id == mem.chan_id + && g_tzcmas[i].size == mem.size) return i; } return -1; @@ -1909,12 +1914,13 @@ static void tzcma_free(int idx) dma_free_size = round_up(g_tzcmas[idx].size, PAGE_SIZE) + TZCMA_LLI_TBL_PAGE * PAGE_SIZE; dma_free_writecombine(tzcma_dev, dma_free_size, - tzcma_cpuAddr[idx], g_tzcmas[idx].phyAddr); + g_tzcmas_internal[idx].cpuAddr, g_tzcmas_internal[idx].phyAddr); if (g_tzcma_channels[idx] != NULL) { dma_release_channel(g_tzcma_channels[idx]); g_tzcma_channels[idx] = NULL; } memset(&g_tzcmas[idx], 0, sizeof(struct tzcma_info)); + memset(&g_tzcmas_internal[idx], 0, sizeof(struct tzcma_info_internal)); } static int tzcma_alloc(int idx, size_t size) @@ -1940,8 +1946,9 @@ static int tzcma_alloc(int idx, size_t size) return -ENOMEM; } g_tzcmas[idx].size = size; - g_tzcmas[idx].phyAddr = phyAddr; - tzcma_cpuAddr[idx] = cpuAddr; + g_tzcmas_internal[idx].is_mmaped = TZCMA_UNMMAPED; + g_tzcmas_internal[idx].phyAddr = phyAddr; + g_tzcmas_internal[idx].cpuAddr = cpuAddr; dma_cap_zero(mask); dma_cap_set(DMA_MEMCPY, mask); @@ -1968,6 +1975,8 @@ static int tzcma_open(struct inode *inode, struct file *file) g_tzcma_state_opened = true; for (i = 0; i < TZCMA_ALLOC_MAX_COUNT; i++) { memset(&g_tzcmas[i], 0, sizeof(struct tzcma_info)); + memset(&g_tzcmas_internal[i], 0, + sizeof(struct tzcma_info_internal)); g_tzcma_channels[i] = NULL; } g_tzcma_alloc_cnt = 0; @@ -1986,8 +1995,9 @@ static int tzcma_mmap(struct file *file, struct vm_area_struct *vma) size = vma->vm_end - vma->vm_start; for (i = 0; i < TZCMA_ALLOC_MAX_COUNT; i++) { - if ((g_tzcmas[i].phyAddr == vma->vm_start) + if ((g_tzcmas_internal[i].is_mmaped == TZCMA_UNMMAPED) && (size == round_up(g_tzcmas[i].size, PAGE_SIZE))) { + g_tzcmas_internal[i].is_mmaped = TZCMA_MMAPED; idx = i; break; } @@ -1997,8 +2007,8 @@ static int tzcma_mmap(struct file *file, struct vm_area_struct *vma) return -ENXIO; } - cpu_addr = tzcma_cpuAddr[idx]; - dma_addr = g_tzcmas[idx].phyAddr; + cpu_addr = g_tzcmas_internal[idx].cpuAddr; + dma_addr = g_tzcmas_internal[idx].phyAddr; ret = dma_mmap_writecombine(tzcma_dev, vma, cpu_addr, dma_addr, size); return ret; @@ -2061,7 +2071,7 @@ static int tzcma_release(struct inode *inode, struct file *file) int ret = 0; for (i = 0; i < TZCMA_ALLOC_MAX_COUNT; i++) { - if (g_tzcmas[i].phyAddr != 0) + if (g_tzcmas_internal[i].phyAddr != 0) tzcma_free(i); } g_tzcma_alloc_cnt = 0; @@ -2242,7 +2252,7 @@ static int __init init_tzdev(void) wake_up_process(thr); } - tzlog_init(); + tzlog_init(secos_kernel_info.build_info); plat_init(); diff --git a/drivers/misc/artiktee/tzdev_smc.c b/drivers/misc/artiktee/tzdev_smc.c index eb5627fffb2f..f93aa72d633e 100644 --- a/drivers/misc/artiktee/tzdev_smc.c +++ b/drivers/misc/artiktee/tzdev_smc.c @@ -22,7 +22,6 @@ #include "tzdev.h" #include "tzdev_internal.h" #include "tzdev_smc.h" -#include "tzpage.h" #include "tzlog_print.h" #include "tzrsrc_msg.h" @@ -44,7 +43,7 @@ static DEFINE_PER_CPU(SMC_STATUS, smc_status_each_core); static void update_smc_status(int cpu, int inout_status, int function_nubmer) { - SMC_STATUS * smc_status; + SMC_STATUS *smc_status; smc_status = &per_cpu(smc_status_each_core, cpu); smc_status->inout_status = inout_status; @@ -55,7 +54,7 @@ static void update_smc_status(int cpu, int inout_status, int function_nubmer) else if (inout_status == 1) do_gettimeofday(&smc_status->smc_out); - if(inout_status == 1) { + if (inout_status == 1) { struct timeval temp; unsigned long difftime; @@ -97,7 +96,7 @@ void init_smc_status(void) smc_status->smc_out.tv_usec = 0; } } -#endif +#endif /* CONFIG_TZDEV_DEBUG */ static inline void __do_call_smc_internal(struct monitor_arguments *args, struct monitor_result *result) @@ -164,7 +163,7 @@ int smc_init_monitor(void) do_call_smc_internal(&args, &res, SMC_OP); if (res.res[0] == -1) { - tzlog_print(TZLOG_INFO, "Failed to query SecureOS UUID.\n"); + tzlog_print(TZLOG_ERROR, "Failed to query SecureOS UUID.\n"); return -1; } uuid.uuid0 = res.res[0]; diff --git a/drivers/misc/artiktee/tzdev_smc.h b/drivers/misc/artiktee/tzdev_smc.h index 12399c50c8ed..f5b8f8a98508 100644 --- a/drivers/misc/artiktee/tzdev_smc.h +++ b/drivers/misc/artiktee/tzdev_smc.h @@ -22,8 +22,8 @@ #define SMC_STANDARD_CALL 0x00000000 #define SMC_FAST_CALL 0x80000000 -#define SMC_32CALL 0x00000000 -#define SMC_64CALL 0x40000000 +#define SMC_32CALL 0x00000000 +#define SMC_64CALL 0x40000000 #define SMC_ENTITY_MASK 0x3F000000 #define SMC_ENTITY_SHIFT 24 diff --git a/drivers/misc/artiktee/tzlinkmgr.c b/drivers/misc/artiktee/tzlinkmgr.c index 68e54f4edbb6..3e7136b5c96a 100644 --- a/drivers/misc/artiktee/tzlinkmgr.c +++ b/drivers/misc/artiktee/tzlinkmgr.c @@ -20,7 +20,6 @@ #include "circular_buffer.h" #include "tzdev.h" #include "tzdev_internal.h" -#include "tzpage.h" #include "tzdev_smc.h" #include "tzlog_print.h" @@ -48,7 +47,7 @@ static struct tzio_link *tzio_alloc_link(gfp_t gfp) } link->mux_link = page_address(link->pg); - link->id = tzwsm_register_tzdev_memory(0, &link->pg, 1, gfp, 1); + link->id = tzwsm_register_tzdev_memory(0, &link->pg, NULL, 1, gfp, 1); if (link->id < 0) { tzlog_print(TZLOG_ERROR, diff --git a/drivers/misc/artiktee/tzlog.c b/drivers/misc/artiktee/tzlog.c index 6d123735f0eb..055b49132cca 100644 --- a/drivers/misc/artiktee/tzlog.c +++ b/drivers/misc/artiktee/tzlog.c @@ -31,7 +31,6 @@ #include "circular_buffer.h" #include "tzdev.h" #include "tzdev_internal.h" -#include "tzpage.h" #include "tzdev_smc.h" /*#define CONFIG_INSTANCE_DEBUG*/ diff --git a/drivers/misc/artiktee/tzlog_core.c b/drivers/misc/artiktee/tzlog_core.c index fcd2fa54f1cd..58b23c88e61e 100644 --- a/drivers/misc/artiktee/tzlog_core.c +++ b/drivers/misc/artiktee/tzlog_core.c @@ -32,7 +32,6 @@ #include "circular_buffer.h" #include "tzdev.h" #include "tzdev_internal.h" -#include "tzpage.h" #include "tzdev_smc.h" #include "ssdev_file.h" @@ -110,7 +109,7 @@ static int tzlog_output_to_error_log(char *data, int data_size, do_gettimeofday(&now); T = (now.tv_sec * 1000ULL) + (now.tv_usec / 1000LL); - file_full_path = (char*)vmalloc(PATH_MAX); + file_full_path = (char *)vmalloc(PATH_MAX); if (file_full_path == NULL) { tzlog_print(K_ERR, "vmalloc failed\n"); ret = -ENOMEM; @@ -125,7 +124,7 @@ static int tzlog_output_to_error_log(char *data, int data_size, tzlog_print(K_INFO, "file_full_path-log %s \n", file_full_path); #if defined(CONFIG_INSTANCE_DEBUG) && defined(CONFIG_USB_DUMP) - if(ss_file_object_exist(file_full_path) == 1) + if (ss_file_object_exist(file_full_path) == 1) copy_file_to_usb(file_full_path); else tzlog_print(K_ERR, "file(%s) not exist \n", file_full_path); @@ -133,7 +132,7 @@ static int tzlog_output_to_error_log(char *data, int data_size, exit_tzlog_output_to_error_log: - if(file_full_path != NULL) + if (file_full_path != NULL) vfree(file_full_path); return ret; @@ -253,7 +252,7 @@ void tzlog_notify(void) up(&log_data.sem); } -void __init tzlog_init(void) +void __init tzlog_init(char *default_msg) { int ret; @@ -277,11 +276,21 @@ void __init tzlog_init(void) GFP_KERNEL); tzlog_print(TZLOG_DEBUG, "TZLOG ring at %p\n", log_data.ring); - if (log_data.ring != NULL) + if (log_data.ring != NULL) { tzlog_print(TZLOG_DEBUG, "ring size %d\n", log_data.ring->size); + if (strlen(default_msg) > 0) { + chimera_ring_buffer_write( + log_data.ring, + (const uint8_t *)default_msg, + strlen(default_msg), + log_data.ring->size + + sizeof(struct chimera_ring_buffer)); + } + } + log_data.log_wsm_id = - tzwsm_register_tzdev_memory(0, &log_data.log_page, + tzwsm_register_tzdev_memory(0, &log_data.log_page, NULL, 1U << TZLOG_PAGE_ORDER, GFP_KERNEL, 1); if (log_data.log_wsm_id < 0) diff --git a/drivers/misc/artiktee/tzlog_core.h b/drivers/misc/artiktee/tzlog_core.h index 73bdfa4ee86c..7348603f27e2 100644 --- a/drivers/misc/artiktee/tzlog_core.h +++ b/drivers/misc/artiktee/tzlog_core.h @@ -40,6 +40,6 @@ typedef struct tzlog_data { } s_tzlog_data; void tzlog_notify(void); -void tzlog_init(void); +void tzlog_init(char *default_msg); #endif /* __TZLOG_CORE_H__ */ diff --git a/drivers/misc/artiktee/tzlog_print.c b/drivers/misc/artiktee/tzlog_print.c index 518d5ceaf5e2..ab78cac38876 100644 --- a/drivers/misc/artiktee/tzlog_print.c +++ b/drivers/misc/artiktee/tzlog_print.c @@ -113,6 +113,10 @@ static int tzlog_print_common( return 0; } +/* + * will be use bit flag for decreasing parameter count. + * we can change log_header_info to use bit flag + */ void tzlog_print_for_tee(uint32_t level, const char *label, const char *fmt, ...) diff --git a/drivers/misc/artiktee/tzmem.c b/drivers/misc/artiktee/tzmem.c index af68f2f8e0e3..68404aa9b403 100644 --- a/drivers/misc/artiktee/tzmem.c +++ b/drivers/misc/artiktee/tzmem.c @@ -34,9 +34,7 @@ #include "tzdev_internal.h" #include "tzlog_print.h" #include "nsrpc_ree_slave.h" -#include "tzpage.h" #include "tzdev_smc.h" -#include "tzwsm.h" static int register_user_memory(struct file *owner, unsigned long base, @@ -205,6 +203,7 @@ struct tzmem_registration { int id; /* WSM id */ size_t num_pages; /* Number of pages */ struct page **pages; /* From get_user_pages() */ + phys_addr_t *pfns; unsigned long tee_ctx_id; /* TEE context ID */ struct file *owner; /* File which owns this WSM */ }; @@ -219,7 +218,8 @@ static void tzmem_registration_free(struct kref *kref) node = container_of(kref, struct tzmem_registration, kref); tzlog_print(TZLOG_DEBUG, "Free WSM %d with ptr %p\n", node->id, node); - tzwsm_unregister_user_memory(node->id, node->pages, node->num_pages); + tzwsm_unregister_user_memory(node->id, node->pages, + node->pfns, node->num_pages); kmem_cache_free(tzmem_registration_slab, node); } @@ -314,7 +314,9 @@ static int register_user_memory(struct file *owner, size, rw ? VERIFY_WRITE : VERIFY_READ, GFP_KERNEL, - &node->pages, &node->num_pages); + &node->pages, + &node->pfns, + &node->num_pages); if (error < 0) { tzlog_print(TZLOG_ERROR, diff --git a/drivers/misc/artiktee/tzsys.c b/drivers/misc/artiktee/tzsys.c index 286cb13ae147..8639abc6eab2 100644 --- a/drivers/misc/artiktee/tzsys.c +++ b/drivers/misc/artiktee/tzsys.c @@ -28,7 +28,6 @@ #include "tzdev.h" #include "tzdev_internal.h" -#include "tzpage.h" #include "tzdev_smc.h" #include "tzlog_print.h" #include "ssdev_file.h" @@ -85,7 +84,7 @@ void __init tzsys_init(void) tz_syspage = (struct secos_syspage *)page_address(pg); - memid = tzwsm_register_tzdev_memory(0, &pg, 1, GFP_KERNEL, 1); + memid = tzwsm_register_tzdev_memory(0, &pg, NULL, 1, GFP_KERNEL, 1); BUG_ON(memid < 0); rc = scm_syscrash_register(memid); @@ -151,7 +150,7 @@ int tzlog_output_do_dump(int is_kernel) do_gettimeofday(&now); T = (now.tv_sec * 1000ULL) + (now.tv_usec / 1000LL); - file_full_path = (char*)vmalloc(PATH_MAX); + file_full_path = (char *)vmalloc(PATH_MAX); if (file_full_path == NULL) { tzlog_print(K_ERR, "vmalloc failed\n"); ret = -1; diff --git a/drivers/misc/artiktee/tzwsm.c b/drivers/misc/artiktee/tzwsm.c index 8ea20e05b0ee..9c490b5a6484 100644 --- a/drivers/misc/artiktee/tzwsm.c +++ b/drivers/misc/artiktee/tzwsm.c @@ -23,13 +23,120 @@ #include <linux/uaccess.h> #include <linux/slab.h> #include "tzdev.h" -#include "tzpage.h" #include "tzdev_smc.h" #include "wsm.h" #include "tzlog_print.h" +#define ARCH_V2P_ERROR 1 + +#ifdef __arm__ +#ifdef CONFIG_ARM_LPAE +static inline phys_addr_t arch_v2p_translate(unsigned long addr, int is_write) +{ + phys_addr_t result; + + if (is_write) { + __asm__ __volatile__( + "MCR p15, 0, %1, c7, c8, 3\n\t" + "ISB\n\t" + "MRRC p15, 0, %Q0, %R0, c7\n\t" + : "=r"(result) + : "r"(addr)); + } else { + __asm__ __volatile__( + "MCR p15, 0, %1, c7, c8, 2\n\t" + "ISB\n\t" + "MRRC p15, 0, %Q0, %R0, c7\n\t" + : "=r"(result) + : "r"(addr)); + } + + if (result & 1) + return ARCH_V2P_ERROR; + + return result & 0x000000FFFFFFF000ULL; +} +#else +static inline phys_addr_t arch_v2p_translate(unsigned long addr, int is_write) +{ + uint32_t result; + + if (is_write) { + __asm__ __volatile__( + "MCR p15, 0, %1, c7, c8, 3\n\t" + "ISB\n\t" + "MRC p15, 0, %0, c7, c4, 0\n\t" + : "=r"(result) + : "r"(addr)); + } else { + __asm__ __volatile__( + "MCR p15, 0, %1, c7, c8, 2\n\t" + "ISB\n\t" + "MRC p15, 0, %0, c7, c4, 0\n\t" + : "=r"(result) + : "r"(addr)); + } + + if (result & 1) + return ARCH_V2P_ERROR; + + /* Supersection */ + if (result & 2) { + return ((phys_addr_t)(result & 0xFF000000)) | + (((phys_addr_t)(result & 0x00FF0000)) << 16) | + (addr & 0x00FFF000); + } + + return result & 0xFFFFF000; +} +#endif /* __arm__ */ +#elif defined(__aarch64__) +static inline phys_addr_t arch_v2p_translate(unsigned long addr, int is_write) +{ + phys_addr_t result; + + if (is_write) { + __asm__ __volatile__( + "AT S1E0W, %1\n\t" + "ISB\n\t" + "mrs %0, PAR_EL1\n\t" + : "=r"(result) + : "r"(addr)); + } else { + __asm__ __volatile__( + "AT S1E0R, %1\n\t" + "ISB\n\t" + "mrs %0, PAR_EL1\n\t" + : "=r"(result) + : "r"(addr)); + } + + if (result & 1) + return ARCH_V2P_ERROR; + + return result & 0x000FFFFFFFFFF000ULL; +} +#else /* __aarch64__ */ +#error "Unsupported TLB operation" +#endif + +static inline phys_addr_t v2p_translate(unsigned long addr, int is_write) +{ + phys_addr_t phys = arch_v2p_translate(addr, is_write); + char c; + + if (phys != ARCH_V2P_ERROR) + return phys; + + if (copy_from_user(&c, (const void * __user)addr, sizeof(c))) + return ARCH_V2P_ERROR; + + return arch_v2p_translate(addr, is_write); +} + int tzwsm_register_tzdev_memory(uint64_t ctx_id, struct page **pages, - size_t num_pages, gfp_t gfp, int for_kernel) + phys_addr_t *pfns, size_t num_pages, + gfp_t gfp, int for_kernel) { struct page *level0_page = NULL; struct page **level1_pages = NULL; @@ -102,11 +209,12 @@ int tzwsm_register_tzdev_memory(uint64_t ctx_id, struct page **pages, tzlog_print(TZLOG_DEBUG, "Level 1 Indirection #%zd Address %llx\n", - l1index, + l1index, (uint64_t)page_to_phys(level1_pages[l1index])); for (j = 0; j < level1->num_pfns; ++j, ++i) { - level1->address[j] = page_to_phys(pages[i]); + level1->address[j] = pages ? + page_to_phys(pages[i]) : pfns[i]; tzlog_print(TZLOG_DEBUG, "Page #%zu Address %llx\n", i, @@ -117,7 +225,8 @@ int tzwsm_register_tzdev_memory(uint64_t ctx_id, struct page **pages, tzlog_print(TZLOG_DEBUG, "No need for level1 pages\n"); for (i = 0; i < num_pages; ++i) { - level0->address[i] = page_to_phys(pages[i]); + level0->address[i] = pages ? + page_to_phys(pages[i]) : pfns[i]; tzlog_print(TZLOG_DEBUG, "Page #%zu Address %llx\n", i, (uint64_t) level0->address[i]); @@ -190,7 +299,7 @@ int tzwsm_register_kernel_memory(const void *ptr, size_t size, gfp_t gfp) } } - result = tzwsm_register_tzdev_memory(0, pages, size, gfp, 1); + result = tzwsm_register_tzdev_memory(0, pages, NULL, size, gfp, 1); kfree(pages); @@ -204,9 +313,11 @@ void tzwsm_unregister_kernel_memory(int wsmid) int tzwsm_register_user_memory(uint64_t ctx_id, const void *__user ptr, size_t size, int rw, gfp_t gfp, - struct page ***p_pages, size_t *p_num_pages) + struct page ***p_pages, phys_addr_t **p_pfns, + size_t *p_num_pages) { struct page **pages; + phys_addr_t *pfns = NULL; size_t num_pages; int error; size_t i; @@ -238,45 +349,112 @@ int tzwsm_register_user_memory(uint64_t ctx_id, const void *__user ptr, error = get_user_pages_fast( (unsigned long)ptr_base, num_pages, 0, pages); + if (error == -EFAULT) { + struct mm_struct *mm; + struct vm_area_struct *vma; + + kfree(pages); + pages = NULL; + + mm = current->mm; + down_read(&mm->mmap_sem); + vma = find_vma(mm, ptr_base); + if (vma != NULL) { + if (vma->vm_flags & (VM_IO | VM_PFNMAP)) { + if (ptr_end <= vma->vm_end) { + error = 0; + } else { + tzlog_print(TZLOG_ERROR, + "wsm: Pointer to PFNMAP %p must fit same vma\n", + ptr); + } + } + } + up_read(&mm->mmap_sem); + + if (error == 0) { + unsigned long trans_addr; + unsigned int index = 0; + + pfns = (phys_addr_t *)kzalloc( + sizeof(phys_addr_t) * num_pages, gfp); + + if (!pfns) + return -ENOMEM; + + for (trans_addr = ptr_base; trans_addr < ptr_end; + trans_addr += PAGE_SIZE) { + pfns[index] = v2p_translate(trans_addr, + rw == VERIFY_READ ? 0 : 1); + + if (pfns[index] == ARCH_V2P_ERROR) { + tzlog_print(TZLOG_ERROR, + "Error translating address %p. You must ensure user mapping %p \exists\n", + (void *)trans_addr, ptr); + error = -EFAULT; + break; + } + + ++index; + } + + if (error == 0) + error = num_pages; + } + } + if (error <= 0) { kfree(pages); + kfree(pfns); return error == 0 ? -EFAULT : error; } - if ((size_t) error != num_pages) { - - for (i = 0; i < (size_t) error; ++i) - put_page(pages[i]); + if ((size_t)error != num_pages) { + if (pages) { + for (i = 0; i < (size_t)error; ++i) + put_page(pages[i]); + } kfree(pages); + kfree(pfns); + return -EFAULT; } - error = tzwsm_register_tzdev_memory(ctx_id, pages, num_pages, gfp, 0); + error = tzwsm_register_tzdev_memory(ctx_id, pages, pfns, num_pages, + gfp, 0); if (error < 0) { - for (i = 0; i < num_pages; ++i) - put_page(pages[i]); + if (pages) { + for (i = 0; i < num_pages; ++i) + put_page(pages[i]); + } + kfree(pfns); kfree(pages); + return error; } *p_pages = pages; *p_num_pages = num_pages; + *p_pfns = pfns; return error; } void tzwsm_unregister_user_memory(int wsmid, struct page **pages, - size_t num_pages) + phys_addr_t *pfns, size_t num_pages) { size_t i; scm_unregister_wsm(wsmid); - for (i = 0; i < num_pages; ++i) - put_page(pages[i]); + if (pages) { + for (i = 0; i < num_pages; ++i) + put_page(pages[i]); + } kfree(pages); + kfree(pfns); } |