blob: e1cb1a435358dcd60884763764c701842f90bb88 [file] [log] [blame]
Patrick Daly23301482017-10-12 16:18:25 -07001/*
Prakash Guptab0d88b72018-05-15 16:08:08 +05302 * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
Patrick Daly23301482017-10-12 16:18:25 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/kernel.h>
16#include <soc/qcom/secure_buffer.h>
17#include <linux/arm-smmu-errata.h>
18
19static struct page *guard_pages[VMID_LAST];
20static DEFINE_MUTEX(guard_page_lock);
21
22struct page *arm_smmu_errata_get_guard_page(int vmid)
23{
24 struct page *page;
25 int ret;
26 int source_vm = VMID_HLOS;
27 int dest_vm = vmid;
28 int dest_perm = PERM_READ | PERM_WRITE | PERM_EXEC;
29 size_t size = ARM_SMMU_MIN_IOVA_ALIGN;
30
31 mutex_lock(&guard_page_lock);
32 page = guard_pages[vmid];
33 if (page)
34 goto out;
35
36 page = alloc_pages(GFP_KERNEL, get_order(size));
37 if (!page)
38 goto out;
39
40 if (vmid != VMID_HLOS) {
41 ret = hyp_assign_phys(page_to_phys(page), PAGE_ALIGN(size),
42 &source_vm, 1,
43 &dest_vm, &dest_perm, 1);
Prakash Guptab0d88b72018-05-15 16:08:08 +053044 if (ret && (ret != -EIO)) {
Patrick Daly23301482017-10-12 16:18:25 -070045 __free_pages(page, get_order(size));
46 page = NULL;
47 }
48 }
49 guard_pages[vmid] = page;
50out:
51 mutex_unlock(&guard_page_lock);
52 return page;
53}