From patchwork Thu Jul 7 08:33:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislav Shmarov X-Patchwork-Id: 9218367 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 AA88E607D9 for ; Thu, 7 Jul 2016 08:34:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9D973287AC for ; Thu, 7 Jul 2016 08:34:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9200A287B3; Thu, 7 Jul 2016 08:34:50 +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.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2427E287AC for ; Thu, 7 Jul 2016 08:34:49 +0000 (UTC) Received: from localhost ([::1]:38203 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bL4lk-0001Pb-BC for patchwork-qemu-devel@patchwork.kernel.org; Thu, 07 Jul 2016 04:34:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55159) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bL4lU-0001PH-56 for qemu-devel@nongnu.org; Thu, 07 Jul 2016 04:34:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bL4lP-0000vF-2u for qemu-devel@nongnu.org; Thu, 07 Jul 2016 04:34:32 -0400 Received: from mail-lf0-x243.google.com ([2a00:1450:4010:c07::243]:34162) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bL4lO-0000v9-Ro for qemu-devel@nongnu.org; Thu, 07 Jul 2016 04:34:27 -0400 Received: by mail-lf0-x243.google.com with SMTP id z185so823020lfd.1 for ; Thu, 07 Jul 2016 01:34:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=AsaL3+i+VX2++m/40bjdN2nAO7oTdJxLHWbU0ScfVeQ=; b=ugF4G7GsBr9b8eVukUwdfKzIG68Fxc8sE+rVwczGQ2ZQQ7pyYp/00pqvIgx0is/azK zMByRMeaVD3T/4jcfGoG0bAiZX42xc9yNWi1KnT51V4Gmcl0xo8/eI9AOJ79n9ABIAIb JpFma6KP7TwwgoJNFFlMp3iHrDybN6pcF2+tf+ml0X5mRzhBPme8KOsmi7XCuF1b2xq1 ut+eb2pzxTPNQtbJw/hso9E3fG5YvKtTljTcCo/DcoOckKMv9MDB8lmG6jDiSzwY5cQf b7T1nUozVNIaG+rCw+BzptBKDeWGDgBCBFAXKvLJ6ooUaLrvNmKewYBTVrsiagKB2B0p AgLg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=AsaL3+i+VX2++m/40bjdN2nAO7oTdJxLHWbU0ScfVeQ=; b=Ure057hYnm+d/9oZGP72sOlgAEAsS81jCDXDx1mwOxNmj2bugUCEipARJia1e/RVxM Od7K61MvwE2id99gmDxOPW+WEiUHtC3B3QIHyjbt3L4nziMNq6VYoTDvr0MxfhM1JE8j 0hWmLtvXj+lwBqM+KQaxzC3MuNU2AP26pZh1y/+gCuf7cIulo24JMQV25sEX7aSj+vYv KO4w1yZXnW/Dnb5qYI8aZrV/8IPHKaYoT/B3ngINuprQPsn0CSkN7H7htMrDuqjURLM7 ZPMO6mwwnR88QaT0UWPEiWQ64EQyMrJlkWU8Ox/OJWniswdOIUPNnlAWqc/4nTBTrIHG WtPw== X-Gm-Message-State: ALyK8tIVxqYqJw4LOZPYikhdGllUiOW8/aJ9wRIsmRJvjkIidBOcEAYpsHNCeeRV+bvsBg== X-Received: by 10.25.23.72 with SMTP id n69mr8070429lfi.64.1467880466034; Thu, 07 Jul 2016 01:34:26 -0700 (PDT) Received: from mlogin26.smware.local ([213.243.91.10]) by smtp.gmail.com with ESMTPSA id h11sm4525797ljh.33.2016.07.07.01.34.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 07 Jul 2016 01:34:25 -0700 (PDT) From: Stanislav Shmarov To: qemu-devel@nongnu.org Date: Thu, 7 Jul 2016 11:33:12 +0300 Message-Id: <1467880392-1043630-1-git-send-email-snarpix@gmail.com> X-Mailer: git-send-email 1.9.3 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:4010:c07::243 Subject: [Qemu-devel] [PATCH v3] translate-all: Bugfix for user-mode self-modifying code in 2 page long TB X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Sergey Fedorov , Richard Henderson , Stanislav Shmarov , Peter Crosthwaite Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP In user-mode emulation Translation Block can consist of 2 guest pages. In that case QEMU also mprotects 2 host pages that are dedicated for guest memory, containing instructions. QEMU detects self-modifying code with SEGFAULT signal processing. In case if instruction in 1st page is modifying memory of 2nd page (or vice versa) QEMU will mark 2nd page with PAGE_WRITE, invalidate TB, generate new TB contatining 1 guest instruction and exit to CPU loop. QEMU won't call mprotect, and new TB will cause same SEGFAULT. Page will have both PAGE_WRITE_ORG and PAGE_WRITE flags, so QEMU will handle the signal as guest binary problem, and exit with guest SEGFAULT. Solution is to do following: In case if current TB was invalidated continue to invalidate TBs from remaining guest pages and mark pages as PAGE_WRITE. After that disable host page protection with mprotect. If current tb was invalidated longjmp to main loop. That is more efficient, since we won't get SEGFAULT when executing new TB. Signed-off-by: Stanislav Shmarov Reviewed-by: Sergey Fedorov Reviewed-by: Richard Henderson --- v3: Now mprotect is called on first SEGFAULT. (Significant changes) v2: Moved setting PAGE_WRITE flag to separte loop, to cover cases, pointed by Sergey Fedorov. translate-all.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/translate-all.c b/translate-all.c index eaa95e4..0d47c1c 100644 --- a/translate-all.c +++ b/translate-all.c @@ -2000,6 +2000,7 @@ int page_check_range(target_ulong start, target_ulong len, int flags) int page_unprotect(target_ulong address, uintptr_t pc) { unsigned int prot; + bool current_tb_invalidated; PageDesc *p; target_ulong host_start, host_end, addr; @@ -2021,6 +2022,7 @@ int page_unprotect(target_ulong address, uintptr_t pc) host_end = host_start + qemu_host_page_size; prot = 0; + current_tb_invalidated = false; for (addr = host_start ; addr < host_end ; addr += TARGET_PAGE_SIZE) { p = page_find(addr >> TARGET_PAGE_BITS); p->flags |= PAGE_WRITE; @@ -2028,10 +2030,7 @@ int page_unprotect(target_ulong address, uintptr_t pc) /* and since the content will be modified, we must invalidate the corresponding translated code. */ - if (tb_invalidate_phys_page(addr, pc)) { - mmap_unlock(); - return 2; - } + current_tb_invalidated |= tb_invalidate_phys_page(addr, pc); #ifdef DEBUG_TB_CHECK tb_invalidate_check(addr); #endif @@ -2040,7 +2039,8 @@ int page_unprotect(target_ulong address, uintptr_t pc) prot & PAGE_BITS); mmap_unlock(); - return 1; + /* If current TB was invalidated return to main loop */ + return current_tb_invalidated ? 2 : 1; } mmap_unlock(); return 0;