From patchwork Wed Jun 13 11:11:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 10462037 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 598DE603B4 for ; Wed, 13 Jun 2018 11:11:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4A626288DA for ; Wed, 13 Jun 2018 11:11:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3CA8B288DD; Wed, 13 Jun 2018 11:11:17 +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=-7.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, 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 946EF288F7 for ; Wed, 13 Jun 2018 11:11:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935253AbeFMLLP (ORCPT ); Wed, 13 Jun 2018 07:11:15 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:36002 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S934677AbeFMLLM (ORCPT ); Wed, 13 Jun 2018 07:11:12 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AF1374023336; Wed, 13 Jun 2018 11:11:11 +0000 (UTC) Received: from thh440s.redhat.com (ovpn-116-24.ams2.redhat.com [10.36.116.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id A81A91C65F; Wed, 13 Jun 2018 11:11:10 +0000 (UTC) From: Thomas Huth To: kvm@vger.kernel.org, =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , Paolo Bonzini Cc: David Hildenbrand , Laurent Vivier , frankja@linux.ibm.com Subject: [kvm-unit-tests PULL 2/3] s390x: IEP tests Date: Wed, 13 Jun 2018 13:11:01 +0200 Message-Id: <1528888262-19694-3-git-send-email-thuth@redhat.com> In-Reply-To: <1528888262-19694-1-git-send-email-thuth@redhat.com> References: <1528888262-19694-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Wed, 13 Jun 2018 11:11:11 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Wed, 13 Jun 2018 11:11:11 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'thuth@redhat.com' RCPT:'' Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Janosch Frank Tests no-execute (Instruction Execution Protection) DAT protection. Signed-off-by: Janosch Frank Acked-by: David Hildenbrand Signed-off-by: Thomas Huth --- lib/s390x/interrupt.c | 6 +++++ lib/s390x/mmu.c | 46 ++++++++++++++++++++++++++++++++++++-- lib/s390x/mmu.h | 20 +++++++++++++++++ s390x/Makefile | 1 + s390x/iep.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ s390x/unittests.cfg | 3 +++ 6 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 lib/s390x/mmu.h create mode 100644 s390x/iep.c diff --git a/lib/s390x/interrupt.c b/lib/s390x/interrupt.c index 56c7603..bc44e3a 100644 --- a/lib/s390x/interrupt.c +++ b/lib/s390x/interrupt.c @@ -51,6 +51,12 @@ static void fixup_pgm_int(void) */ lc->pgm_old_psw.mask &= ~PSW_MASK_PSTATE; break; + case PGM_INT_CODE_PROTECTION: + /* Handling for iep.c test case. */ + if (lc->trans_exc_id & 0x80UL && lc->trans_exc_id & 0x04UL && + !(lc->trans_exc_id & 0x08UL)) + lc->pgm_old_psw.addr = lc->sw_int_grs[14]; + break; case PGM_INT_CODE_SEGMENT_TRANSLATION: case PGM_INT_CODE_PAGE_TRANSLATION: case PGM_INT_CODE_TRACE_TABLE: diff --git a/lib/s390x/mmu.c b/lib/s390x/mmu.c index 288f835..70753c3 100644 --- a/lib/s390x/mmu.c +++ b/lib/s390x/mmu.c @@ -16,6 +16,8 @@ #include #include +static pgd_t *table_root; + void configure_dat(int enable) { uint64_t mask; @@ -62,7 +64,7 @@ phys_addr_t virt_to_pte_phys(pgd_t *pgtable, void *vaddr) ((unsigned long)vaddr & ~PAGE_MASK); } -pteval_t *install_page(pgd_t *pgtable, phys_addr_t phys, void *vaddr) +static pteval_t *set_pte(pgd_t *pgtable, pteval_t val, void *vaddr) { pteval_t *p_pte = get_pte(pgtable, (uintptr_t)vaddr); @@ -70,10 +72,49 @@ pteval_t *install_page(pgd_t *pgtable, phys_addr_t phys, void *vaddr) if (!(*p_pte & PAGE_ENTRY_I)) ipte((uintptr_t)vaddr, p_pte); - *p_pte = __pa(phys); + *p_pte = val; return p_pte; } +pteval_t *install_page(pgd_t *pgtable, phys_addr_t phys, void *vaddr) +{ + return set_pte(pgtable, __pa(phys), vaddr); +} + +void protect_page(void *vaddr, unsigned long prot) +{ + pteval_t *p_pte = get_pte(table_root, (uintptr_t)vaddr); + pteval_t n_pte = *p_pte | prot; + + set_pte(table_root, n_pte, vaddr); +} + +void unprotect_page(void *vaddr, unsigned long prot) +{ + pteval_t *p_pte = get_pte(table_root, (uintptr_t)vaddr); + pteval_t n_pte = *p_pte & ~prot; + + set_pte(table_root, n_pte, vaddr); +} + +void protect_range(void *start, unsigned long len, unsigned long prot) +{ + uintptr_t curr = (uintptr_t)start & PAGE_MASK; + + len &= PAGE_MASK; + for (; len; len -= PAGE_SIZE, curr += PAGE_SIZE) + protect_page((void *)curr, prot); +} + +void unprotect_range(void *start, unsigned long len, unsigned long prot) +{ + uintptr_t curr = (uintptr_t)start & PAGE_MASK; + + len &= PAGE_MASK; + for (; len; len -= PAGE_SIZE, curr += PAGE_SIZE) + unprotect_page((void *)curr, prot); +} + static void setup_identity(pgd_t *pgtable, phys_addr_t start_addr, phys_addr_t end_addr) { @@ -104,5 +145,6 @@ void *setup_mmu(phys_addr_t phys_end){ /* finally enable DAT with the new table */ mmu_enable(page_root); + table_root = page_root; return page_root; } diff --git a/lib/s390x/mmu.h b/lib/s390x/mmu.h new file mode 100644 index 0000000..f5095fa --- /dev/null +++ b/lib/s390x/mmu.h @@ -0,0 +1,20 @@ +/* + * s390x mmu functions + * + * Copyright (c) 2018 IBM Corp + * + * Authors: + * Janosch Frank + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ +#ifndef _ASMS390X_MMU_H_ +#define _ASMS390X_MMU_H_ + +void protect_page(void *vaddr, unsigned long prot); +void protect_range(void *start, unsigned long len, unsigned long prot); +void unprotect_page(void *vaddr, unsigned long prot); +void unprotect_range(void *start, unsigned long len, unsigned long prot); + +#endif /* _ASMS390X_MMU_H_ */ diff --git a/s390x/Makefile b/s390x/Makefile index abc3242..d4275a1 100644 --- a/s390x/Makefile +++ b/s390x/Makefile @@ -9,6 +9,7 @@ tests += $(TEST_DIR)/pfmf.elf tests += $(TEST_DIR)/cmm.elf tests += $(TEST_DIR)/vector.elf tests += $(TEST_DIR)/gs.elf +tests += $(TEST_DIR)/iep.elf all: directories test_cases diff --git a/s390x/iep.c b/s390x/iep.c new file mode 100644 index 0000000..e4abc72 --- /dev/null +++ b/s390x/iep.c @@ -0,0 +1,62 @@ +/* + * Instruction Execution Prevention (IEP) DAT test. + * + * Copyright (c) 2018 IBM Corp + * + * Authors: + * Janosch Frank + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ +#include +#include +#include +#include +#include +#include +#include + +static void test_iep(void) +{ + uint16_t *code; + uint8_t *iepbuf = NULL; + void (*fn)(void); + + /* Enable IEP */ + ctl_set_bit(0, 20); + + /* Get and protect a page with the IEP bit */ + iepbuf = alloc_page(); + protect_page(iepbuf, PAGE_ENTRY_IEP); + + /* Code branches into r14 which contains the return address. */ + code = (uint16_t *)iepbuf; + *code = 0x07fe; + fn = (void *)code; + + expect_pgm_int(); + /* Jump into protected page */ + fn(); + check_pgm_int_code(PGM_INT_CODE_PROTECTION); + unprotect_page(iepbuf, PAGE_ENTRY_IEP); + ctl_clear_bit(0, 20); +} + +int main(void) +{ + bool has_iep = test_facility(130); + + report_prefix_push("iep"); + report_xfail("DAT IEP available", !has_iep, has_iep); + if (!has_iep) + goto done; + + /* Setup DAT 1:1 mapping and memory management */ + setup_vm(); + test_iep(); + +done: + report_prefix_pop(); + return report_summary(); +} diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg index ff7eea1..e53c365 100644 --- a/s390x/unittests.cfg +++ b/s390x/unittests.cfg @@ -55,3 +55,6 @@ file = vector.elf [gs] file = gs.elf + +[iep] +file = iep.elf