From patchwork Sun Apr 28 08:32:17 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: jordan.l.justen@intel.com X-Patchwork-Id: 240259 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 8B9992C00AE for ; Mon, 29 Apr 2013 01:44:11 +1000 (EST) Received: from localhost ([::1]:54849 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UWTlp-0002aa-QM for incoming@patchwork.ozlabs.org; Sun, 28 Apr 2013 11:44:09 -0400 Received: from eggs.gnu.org ([208.118.235.92]:48289) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UWN2E-00048d-7P for qemu-devel@nongnu.org; Sun, 28 Apr 2013 04:32:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UWN28-0006mB-8F for qemu-devel@nongnu.org; Sun, 28 Apr 2013 04:32:38 -0400 Received: from mga14.intel.com ([143.182.124.37]:44527) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UWN28-0006ld-1t for qemu-devel@nongnu.org; Sun, 28 Apr 2013 04:32:32 -0400 Received: from azsmga002.ch.intel.com ([10.2.17.35]) by azsmga102.ch.intel.com with ESMTP; 28 Apr 2013 01:32:30 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.87,566,1363158000"; d="scan'208";a="233796218" Received: from unknown (HELO jljusten-ivy.amr.corp.intel.com) ([10.255.12.60]) by AZSMGA002.ch.intel.com with ESMTP; 28 Apr 2013 01:32:30 -0700 From: Jordan Justen To: qemu-devel@nongnu.org Date: Sun, 28 Apr 2013 01:32:17 -0700 Message-Id: <1367137941-4310-3-git-send-email-jordan.l.justen@intel.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1367137941-4310-1-git-send-email-jordan.l.justen@intel.com> References: <1367137941-4310-1-git-send-email-jordan.l.justen@intel.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 143.182.124.37 X-Mailman-Approved-At: Sun, 28 Apr 2013 11:42:14 -0400 Cc: Jordan Justen , Xiao Guangrong Subject: [Qemu-devel] [PATCH 2/6] kvm: support using KVM_MEM_READONLY flag for readonly regions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org A slot that uses KVM_MEM_READONLY can be read from and code can execute from the region, but writes will trap. For regions that are readonly and also not writeable, we force the slot to be removed so reads or writes to the region will trap. (A memory region in this state is not executable within kvm.) Signed-off-by: Jordan Justen Cc: Xiao Guangrong Reviewed-by: Xiao Guangrong --- kvm-all.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index f634c41..95e6bf2 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -266,9 +266,14 @@ err: * dirty pages logging control */ -static int kvm_mem_flags(KVMState *s, bool log_dirty) +static int kvm_mem_flags(KVMState *s, bool log_dirty, bool readonly) { - return log_dirty ? KVM_MEM_LOG_DIRTY_PAGES : 0; + int flags = 0; + flags = log_dirty ? KVM_MEM_LOG_DIRTY_PAGES : 0; + if (readonly && kvm_readonly_mem_allowed) { + flags |= KVM_MEM_READONLY; + } + return flags; } static int kvm_slot_dirty_pages_log_change(KVMSlot *mem, bool log_dirty) @@ -279,7 +284,7 @@ static int kvm_slot_dirty_pages_log_change(KVMSlot *mem, bool log_dirty) old_flags = mem->flags; - flags = (mem->flags & ~mask) | kvm_mem_flags(s, log_dirty); + flags = (mem->flags & ~mask) | kvm_mem_flags(s, log_dirty, false); mem->flags = flags; /* If nothing changed effectively, no need to issue ioctl */ @@ -636,7 +641,14 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add) } if (!memory_region_is_ram(mr)) { - return; + if (!mr->readonly || !kvm_readonly_mem_allowed) { + return; + } else if (!mr->readable && add) { + /* If the memory range is not readable, then we actually want + * to remove the kvm memory slot so all accesses will trap. */ + assert(mr->readonly && kvm_readonly_mem_allowed); + add = false; + } } ram = memory_region_get_ram_ptr(mr) + section->offset_within_region + delta; @@ -685,7 +697,7 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add) mem->memory_size = old.memory_size; mem->start_addr = old.start_addr; mem->ram = old.ram; - mem->flags = kvm_mem_flags(s, log_dirty); + mem->flags = kvm_mem_flags(s, log_dirty, mr->readonly); err = kvm_set_user_memory_region(s, mem); if (err) { @@ -706,7 +718,7 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add) mem->memory_size = start_addr - old.start_addr; mem->start_addr = old.start_addr; mem->ram = old.ram; - mem->flags = kvm_mem_flags(s, log_dirty); + mem->flags = kvm_mem_flags(s, log_dirty, mr->readonly); err = kvm_set_user_memory_region(s, mem); if (err) { @@ -730,7 +742,7 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add) size_delta = mem->start_addr - old.start_addr; mem->memory_size = old.memory_size - size_delta; mem->ram = old.ram + size_delta; - mem->flags = kvm_mem_flags(s, log_dirty); + mem->flags = kvm_mem_flags(s, log_dirty, mr->readonly); err = kvm_set_user_memory_region(s, mem); if (err) { @@ -752,7 +764,7 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add) mem->memory_size = size; mem->start_addr = start_addr; mem->ram = ram; - mem->flags = kvm_mem_flags(s, log_dirty); + mem->flags = kvm_mem_flags(s, log_dirty, mr->readonly); err = kvm_set_user_memory_region(s, mem); if (err) {