From patchwork Thu Nov 3 08:04:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 9410569 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id EA14360573 for ; Thu, 3 Nov 2016 08:05:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DBF332A60E for ; Thu, 3 Nov 2016 08:05:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D03B42A61B; Thu, 3 Nov 2016 08:05:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5F5882A60E for ; Thu, 3 Nov 2016 08:05:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755346AbcKCIFN (ORCPT ); Thu, 3 Nov 2016 04:05:13 -0400 Received: from mailout3.w1.samsung.com ([210.118.77.13]:8784 "EHLO mailout3.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755444AbcKCIFF (ORCPT ); Thu, 3 Nov 2016 04:05:05 -0400 Received: from eucas1p1.samsung.com (unknown [182.198.249.206]) by mailout3.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0OG200HUB3SDW280@mailout3.w1.samsung.com> for linux-samsung-soc@vger.kernel.org; Thu, 03 Nov 2016 08:05:01 +0000 (GMT) Received: from eusmges5.samsung.com (unknown [203.254.199.245]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20161103080500eucas1p19b5302339aa228d854b7be9bf9d066b3~DevY-l8zq1137411374eucas1p1J; Thu, 3 Nov 2016 08:05:00 +0000 (GMT) Received: from eucas1p1.samsung.com ( [182.198.249.206]) by eusmges5.samsung.com (EUCPMTA) with SMTP id BA.83.19540.CAFEA185; Thu, 3 Nov 2016 08:05:00 +0000 (GMT) Received: from eusmgms2.samsung.com (unknown [182.198.249.180]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20161103080459eucas1p254076fdf45c72dbc09aee42fe6234c0d~DevYR7VM40259702597eucas1p2G; Thu, 3 Nov 2016 08:04:59 +0000 (GMT) X-AuditID: cbfec7f5-f79ce6d000004c54-70-581aefacaedd Received: from eusync4.samsung.com ( [203.254.199.214]) by eusmgms2.samsung.com (EUCPMTA) with SMTP id 05.7D.10494.C8FEA185; Thu, 3 Nov 2016 08:04:28 +0000 (GMT) Received: from AMDC2765.digital.local ([106.116.147.25]) by eusync4.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0OG200K363S75C40@eusync4.samsung.com>; Thu, 03 Nov 2016 08:04:59 +0000 (GMT) From: Marek Szyprowski To: iommu@lists.linux-foundation.org, linux-samsung-soc@vger.kernel.org Cc: Marek Szyprowski , Joerg Roedel , Inki Dae , Kukjin Kim , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz Subject: [PATCH] iommu/exynos: Add support for page access protection bits Date: Thu, 03 Nov 2016 09:04:45 +0100 Message-id: <1478160285-14214-1-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.1 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrAIsWRmVeSWpSXmKPExsWy7djPc7pr3ktFGJw7KWexccZ6VotJ9yew WCzYb23ROXsDu0X/49fMFufPA1kzzu9jslh75C67A4fHk4PzmDw2repk85h8YzmjR9+WVYwe nzfJBbBGcdmkpOZklqUW6dslcGWsOTqfpeCiQcXME9PZGhhnqncxcnJICJhInNr2iwXCFpO4 cG89WxcjF4eQwFJGiZtTz7BAOJ8ZJQ4132GG6Xj8ewtUYhmjRPf66awQTgOTxKKN15hAqtgE DCW63naxgdgiAu4S1/88B+tgFvjEKHGmoxFslLCAl8SZ9hawBhYBVYmmo8+AGjg4eAU8JFa/ gLpPTuLksclgCyQEbrNJLPz7nwmkRkJAVmLTAaiLXCS2NT5nh7CFJV4d3wJly0hcntwN9Vs/ o0RTqzaEPYNR4txbXgjbWuLw8YusIDazAJ/EpG3TmSHG80p0tAlBlHhIfHz/BGqko8TNWY8Y QWwhgViJaavOM09glF7AyLCKUSS1tDg3PbXYVK84Mbe4NC9dLzk/dxMjMF5P/zv+dQfj0mNW hxgFOBiVeHgFvklGCLEmlhVX5h5ilOBgVhLhPfVcKkKINyWxsiq1KD++qDQntfgQozQHi5I4 754FV8KFBNITS1KzU1MLUotgskwcnFINjJtmHhHYr5EiuvrQ0eIZk1jrd7Mtkgj39rQXzjk/ 0ep95t8/F+0uZT29xnhdrjhqicnEz5sf/4zed5T9tgNr1PUq7QmCD9yi4k+/05Ra3nV2bvxZ Vpe/YjExrIyPVDlKF2Qr3aw47sAbISDz6IKzstjLrZvyzt9zkblQ3rZ8ZtCa2QUXeXd+zVZi Kc5INNRiLipOBAA2gx610wIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrKLMWRmVeSWpSXmKPExsVy+t/xa7o976UiDDpemFpsnLGe1WLS/Qks Fgv2W1t0zt7AbtH/+DWzxfnzQNaM8/uYLNYeucvuwOHx5OA8Jo9NqzrZPCbfWM7o0bdlFaPH 501yAaxRbjYZqYkpqUUKqXnJ+SmZeem2SqEhbroWSgp5ibmptkoRur4hQUoKZYk5pUCekQEa cHAOcA9W0rdLcMtYc3Q+S8FFg4qZJ6azNTDOVO9i5OSQEDCRePx7CwuELSZx4d56ti5GLg4h gSWMEj+fLWWFcJqYJC4tmcIGUsUmYCjR9bYLzBYRcJe4/uc5C0gRs8AnRon2J21gCWEBL4kz 7S1MIDaLgKpE09FnQHEODl4BD4nVL6A2y0mcPDaZdQIj9wJGhlWMIqmlxbnpucVGesWJucWl eel6yfm5mxiBQbrt2M8tOxi73gUfYhTgYFTi4d3xWTJCiDWxrLgy9xCjBAezkgjvqedSEUK8 KYmVValF+fFFpTmpxYcYTYF2T2SWEk3OB0ZQXkm8oYmhuaWhkbGFhbmRkZI479QPV8KFBNIT S1KzU1MLUotg+pg4OKUaGM+m32+sFZHbfrcx9fo10ehTvr4fhFqk+9u3fzOMFck8r1C66LY5 J+vfacvq162+q9bdaRZccOVAljrjDet191msGDgC1y1Sj5STOpVzvfHZoRuuOR+r9KcdDTi1 ItrhvPY3p6ZVvJ9CpFVEtijo8OV87N/I+vm+ysfpMT1ut9O/FPPN50xVVWIpzkg01GIuKk4E APlaLHhoAgAA X-MTR: 20000000000000000@CPGS X-CMS-MailID: 20161103080459eucas1p254076fdf45c72dbc09aee42fe6234c0d X-Msg-Generator: CA X-Sender-IP: 182.198.249.180 X-Local-Sender: =?UTF-8?B?TWFyZWsgU3p5cHJvd3NraRtTUlBPTC1LZXJuZWwgKFRQKRs=?= =?UTF-8?B?7IK87ISx7KCE7J6QG1NlbmlvciBTb2Z0d2FyZSBFbmdpbmVlcg==?= X-Global-Sender: =?UTF-8?B?TWFyZWsgU3p5cHJvd3NraRtTUlBPTC1LZXJuZWwgKFRQKRtT?= =?UTF-8?B?YW1zdW5nIEVsZWN0cm9uaWNzG1NlbmlvciBTb2Z0d2FyZSBFbmdpbmVlcg==?= X-Sender-Code: =?UTF-8?B?QzEwG0VIURtDMTBDRDAyQ0QwMjczOTI=?= CMS-TYPE: 201P X-HopCount: 7 X-CMS-RootMailID: 20161103080459eucas1p254076fdf45c72dbc09aee42fe6234c0d X-RootMTR: 20161103080459eucas1p254076fdf45c72dbc09aee42fe6234c0d References: Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch add support for page access protection bits. Till now this feature was disabled and Exynos SYSMMU always mapped pages as read/write. Now page access bits are set according to the protection bits provided in iommu_map(), so Exynos SYSMMU is able to detect incorrect access to mapped pages. Exynos SYSMMU earlier than v5 doesn't support write-only mappings, so pages with such protection bits are mapped as read/write. Signed-off-by: Marek Szyprowski --- drivers/iommu/exynos-iommu.c | 63 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 30808e9..e249e2f 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -70,6 +70,36 @@ #define SYSMMU_PG_ENT_SHIFT 0 #define SYSMMU_V5_PG_ENT_SHIFT 4 +static const sysmmu_pte_t *LV1_PROT; +static const sysmmu_pte_t SYSMMU_LV1_PROT[] = { + ((0 << 15) | (0 << 10)), /* no access */ + ((1 << 15) | (1 << 10)), /* IOMMU_READ only */ + ((0 << 15) | (1 << 10)), /* IOMMU_WRITE not supported, use read/write */ + ((0 << 15) | (1 << 10)), /* IOMMU_READ | IOMMU_WRITE */ +}; +static const sysmmu_pte_t SYSMMU_V5_LV1_PROT[] = { + (0 << 4), /* no access */ + (1 << 4), /* IOMMU_READ only */ + (2 << 4), /* IOMMU_WRITE only */ + (3 << 4), /* IOMMU_READ | IOMMU_WRITE */ +}; + +static const sysmmu_pte_t *LV2_PROT; +static const sysmmu_pte_t SYSMMU_LV2_PROT[] = { + ((0 << 9) | (0 << 4)), /* no access */ + ((1 << 9) | (1 << 4)), /* IOMMU_READ only */ + ((0 << 9) | (1 << 4)), /* IOMMU_WRITE not supported, use read/write */ + ((0 << 9) | (1 << 4)), /* IOMMU_READ | IOMMU_WRITE */ +}; +static const sysmmu_pte_t SYSMMU_V5_LV2_PROT[] = { + (0 << 2), /* no access */ + (1 << 2), /* IOMMU_READ only */ + (2 << 2), /* IOMMU_WRITE only */ + (3 << 2), /* IOMMU_READ | IOMMU_WRITE */ +}; + +#define SYSMMU_SUPPORTED_PROT_BITS (IOMMU_READ | IOMMU_WRITE) + #define sect_to_phys(ent) (((phys_addr_t) ent) << PG_ENT_SHIFT) #define section_phys(sent) (sect_to_phys(*(sent)) & SECT_MASK) #define section_offs(iova) (iova & (SECT_SIZE - 1)) @@ -97,16 +127,17 @@ static u32 lv2ent_offset(sysmmu_iova_t iova) #define SPAGES_PER_LPAGE (LPAGE_SIZE / SPAGE_SIZE) #define lv2table_base(sent) (sect_to_phys(*(sent) & 0xFFFFFFC0)) -#define mk_lv1ent_sect(pa) ((pa >> PG_ENT_SHIFT) | 2) +#define mk_lv1ent_sect(pa, prot) ((pa >> PG_ENT_SHIFT) | LV1_PROT[prot] | 2) #define mk_lv1ent_page(pa) ((pa >> PG_ENT_SHIFT) | 1) -#define mk_lv2ent_lpage(pa) ((pa >> PG_ENT_SHIFT) | 1) -#define mk_lv2ent_spage(pa) ((pa >> PG_ENT_SHIFT) | 2) +#define mk_lv2ent_lpage(pa, prot) ((pa >> PG_ENT_SHIFT) | LV2_PROT[prot] | 1) +#define mk_lv2ent_spage(pa, prot) ((pa >> PG_ENT_SHIFT) | LV2_PROT[prot] | 2) #define CTRL_ENABLE 0x5 #define CTRL_BLOCK 0x7 #define CTRL_DISABLE 0x0 #define CFG_LRU 0x1 +#define CFG_EAP (1 << 2) #define CFG_QOS(n) ((n & 0xF) << 7) #define CFG_ACGEN (1 << 24) /* System MMU 3.3 only */ #define CFG_SYSSEL (1 << 22) /* System MMU 3.2 only */ @@ -481,6 +512,8 @@ static void __sysmmu_init_config(struct sysmmu_drvdata *data) else cfg = CFG_QOS(15) | CFG_FLPDCACHE | CFG_ACGEN; + cfg |= CFG_EAP; /* enable access protection bits check */ + writel(cfg, data->sfrbase + REG_MMU_CFG); } @@ -652,10 +685,15 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) __sysmmu_get_version(data); if (PG_ENT_SHIFT < 0) { - if (MMU_MAJ_VER(data->version) < 5) + if (MMU_MAJ_VER(data->version) < 5) { PG_ENT_SHIFT = SYSMMU_PG_ENT_SHIFT; - else + LV1_PROT = SYSMMU_LV1_PROT; + LV2_PROT = SYSMMU_LV2_PROT; + } else { PG_ENT_SHIFT = SYSMMU_V5_PG_ENT_SHIFT; + LV1_PROT = SYSMMU_V5_LV1_PROT; + LV2_PROT = SYSMMU_V5_LV2_PROT; + } } pm_runtime_enable(dev); @@ -954,7 +992,7 @@ static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *domain, static int lv1set_section(struct exynos_iommu_domain *domain, sysmmu_pte_t *sent, sysmmu_iova_t iova, - phys_addr_t paddr, short *pgcnt) + phys_addr_t paddr, int prot, short *pgcnt) { if (lv1ent_section(sent)) { WARN(1, "Trying mapping on 1MiB@%#08x that is mapped", @@ -973,7 +1011,7 @@ static int lv1set_section(struct exynos_iommu_domain *domain, *pgcnt = 0; } - update_pte(sent, mk_lv1ent_sect(paddr)); + update_pte(sent, mk_lv1ent_sect(paddr, prot)); spin_lock(&domain->lock); if (lv1ent_page_zero(sent)) { @@ -991,13 +1029,13 @@ static int lv1set_section(struct exynos_iommu_domain *domain, } static int lv2set_page(sysmmu_pte_t *pent, phys_addr_t paddr, size_t size, - short *pgcnt) + int prot, short *pgcnt) { if (size == SPAGE_SIZE) { if (WARN_ON(!lv2ent_fault(pent))) return -EADDRINUSE; - update_pte(pent, mk_lv2ent_spage(paddr)); + update_pte(pent, mk_lv2ent_spage(paddr, prot)); *pgcnt -= 1; } else { /* size == LPAGE_SIZE */ int i; @@ -1013,7 +1051,7 @@ static int lv2set_page(sysmmu_pte_t *pent, phys_addr_t paddr, size_t size, return -EADDRINUSE; } - *pent = mk_lv2ent_lpage(paddr); + *pent = mk_lv2ent_lpage(paddr, prot); } dma_sync_single_for_device(dma_dev, pent_base, sizeof(*pent) * SPAGES_PER_LPAGE, @@ -1061,13 +1099,14 @@ static int exynos_iommu_map(struct iommu_domain *iommu_domain, int ret = -ENOMEM; BUG_ON(domain->pgtable == NULL); + prot &= SYSMMU_SUPPORTED_PROT_BITS; spin_lock_irqsave(&domain->pgtablelock, flags); entry = section_entry(domain->pgtable, iova); if (size == SECT_SIZE) { - ret = lv1set_section(domain, entry, iova, paddr, + ret = lv1set_section(domain, entry, iova, paddr, prot, &domain->lv2entcnt[lv1ent_offset(iova)]); } else { sysmmu_pte_t *pent; @@ -1078,7 +1117,7 @@ static int exynos_iommu_map(struct iommu_domain *iommu_domain, if (IS_ERR(pent)) ret = PTR_ERR(pent); else - ret = lv2set_page(pent, paddr, size, + ret = lv2set_page(pent, paddr, size, prot, &domain->lv2entcnt[lv1ent_offset(iova)]); }