From nobody Thu Apr 2 20:14:35 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E9AAF3A8741 for ; Thu, 26 Mar 2026 18:17:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774549077; cv=none; b=M2jLZOfGcwAR5Lirwx0+Cnr7KSLeKJvcNooaR1XXtEcQuaVysx3iezMJ7fl5bQh65YlL+eQ4MsgfzoI7AfgpylfluaGGGu7O7Ydt2AHlWGfIC2QKO9smfXk2tTWNwDc3v01YDPLn+NIQ+F7QdjdhInpDNn+BDbVR2DN9gQlAFjo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774549077; c=relaxed/simple; bh=V/j0bLtLOQJRuJo1v2hvbWXQwZPcKv+m9rMFbbyuUo0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DNai7iNEclgDvgDgUWMe5tk6DLK3pw3mgz7HGGhTE64nqOaPXrDHiTrRBvUzbXxV1phSHHCqj1A4nONFW5P4jVJ0tuftVsHpxfpHp3rQOgFDeiX9stCcnJeQM6cPnqQxV6BnJPF1xFxDWok858mYvc3AxkwVhFeHofQ9ZAT7KPA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=GVfPtb+U; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=P4VQIWvM; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="GVfPtb+U"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="P4VQIWvM" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1774549071; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0LD9F/oJ5sRufl5xgAEZXqtBZxVR/nArSRHajjH786M=; b=GVfPtb+Ub3VUQSIu5pyeZ266JlUHpl32kRJzzIjDoseWowI27wls8ICYFHTomvYxMoFh0z xp87o5DL75vM8MuBZW98qOPORzMO6hd/FLRi7cZ2hvXcaiyafqIdziIq5Pauvz02rUuSIQ VaBOI5C+d13OnOCRFJxu4aEhUOo5Udk= Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-537-cRlBkD80OLKydE4Zm6Woow-1; Thu, 26 Mar 2026 14:17:50 -0400 X-MC-Unique: cRlBkD80OLKydE4Zm6Woow-1 X-Mimecast-MFC-AGG-ID: cRlBkD80OLKydE4Zm6Woow_1774549068 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-43b42eee946so1799582f8f.1 for ; Thu, 26 Mar 2026 11:17:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1774549067; x=1775153867; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=0LD9F/oJ5sRufl5xgAEZXqtBZxVR/nArSRHajjH786M=; b=P4VQIWvMthmWzk+/Dzwf8teLT8DpPe7rNwkaeH3+aa6+IaAzdSovNFaxuhR0L3HxRc xgwM9viROgxAIvWa7kNBhzrDKNfvy4YH1bLAMwZrBlvt43GxcRYheen/I8F49qRwuh2i aR2dR0rYAPE0MwYpJhrjZYHjehO2OtYtQ04/uV0K6a2qi8BB2iXhc1MEc5a+xj/PC7kB sOw4xnc5O0mz0orT4b/I+0omNVfAudjH2TV8wlfQd+0KVC/IEm6DNzqhDo8qgJKliPAI zZQuLMuZWi+k4J/1IBh27IunY8b4+mCudPel+h84tE/8+Xi59BfqjFoC8h16mO+OulPQ CWtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774549067; x=1775153867; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=0LD9F/oJ5sRufl5xgAEZXqtBZxVR/nArSRHajjH786M=; b=o7Eee7jez6kIAO3MV62hZU9kE/ns2wTWXLmWt4HtCS/xKdFhV7yvdsjZK9woj8Hjfi bl8QyI3d+Se5iFmzc+i3Tc0JlncUD4Bve6UHWsX4gYhZxxq8OtKxHZxb0KwKfBRs8juF C1nOIMCoZxME9AI9o4lOgrm1SQ2kUd4VErj+bxx0onyaS0fab5ucWVc8fIfDp65einuP TawLYMXROZToRoahZTC8LPHEFHwGTh9yJyJCCXL/uSTGS5uB6cW+DJuc3TnREPV+/84F JNVcekcjiW9o2XJPRICB6iwKWyo1BrdShdNAWAoJtIC7n6GWpiyWjX8ugZ4p+brohArO NjGw== X-Gm-Message-State: AOJu0YxHe5nyg6RONzFKFSVlNeGlIzaEOYUrUHlNS8fW9wGhwA327yIz ISeK/CInojUp83+6VG5O2XiKXC4bi0g5NsvJgwmj4+jQ4mnBDq23jpf4HWXt0w6UqT2VdZJsuXd j/R9LPlDYqpGq2e9AuXnhoCGDfQPNScMAubnn33euKWo+DkL59zQaGADSv+ngVSkH9dHn3oU0ci dIAdxEfpXhyirRBzHwMhauyGR+2vishvVxdlwHDAsSxcvgfxw0EQ== X-Gm-Gg: ATEYQzzkD/oGJeo/hqrB730NHV3Y8Shfeoat5hv5GMokT6S/6SUTlLF3otj1/yppBVV pwauPB+GAYni16buppn7Fg1DqzovZVRrMLx9QxtWBAbmeO4c8qULTV0DWZnxEdQAkFLQ0Ppct1q SHQioCQzg4RZ7Migk7J0YFhjUXfcv5bpv0pO9iG3AHlm/cZpRF3PZu07GEYe8fen+utpkEVuQlb nICnR9ionPVOAU3unCW9jkCIFKPMegis5SpWrKGoTkHfFU0BpI2LT0UiWAP9YFa1bd3I+E+PQ12 T/oxCDCZns39Q7aowgk0jWUxauOvdYM3/EtxhJkYY6a2DYsKVS1qv6FiU81lyTHo/AghFolIhXV wPi7/skRYAZcaUqExKDQ9CcAvS5pwi6yIWU9JdSt8wLH2wEGB7QzdmvQ9Hk3hjyfUGyuIAr+Mgp +9vuVlcX4R5wzDs8S++iMMoT92 X-Received: by 2002:a05:6000:1786:b0:43b:945c:e557 with SMTP id ffacd0b85a97d-43b97a1f474mr5123384f8f.11.1774549066334; Thu, 26 Mar 2026 11:17:46 -0700 (PDT) X-Received: by 2002:a05:6000:1786:b0:43b:945c:e557 with SMTP id ffacd0b85a97d-43b97a1f474mr5123279f8f.11.1774549065524; Thu, 26 Mar 2026 11:17:45 -0700 (PDT) Received: from [192.168.10.48] ([151.49.85.67]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-43b919cf2c8sm9012428f8f.20.2026.03.26.11.17.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Mar 2026 11:17:44 -0700 (PDT) From: Paolo Bonzini To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Jon Kohler , Nikunj A Dadhania , Amit Shah , Sean Christopherson , Marcelo Tosatti Subject: [PATCH 08/24] KVM: x86/mmu: introduce ACC_READ_MASK Date: Thu, 26 Mar 2026 19:17:06 +0100 Message-ID: <20260326181723.218115-9-pbonzini@redhat.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260326181723.218115-1-pbonzini@redhat.com> References: <20260326181723.218115-1-pbonzini@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Read permissions so far were only needed for EPT, which does not need ACC_USER_MASK. Therefore, for EPT page tables ACC_USER_MASK was repurposed as a read permission bit. In order to implement nested MBEC, EPT will genuinely have four kinds of accesses, and there will be no room for such hacks; bite the bullet at last, enlarging ACC_ALL to four bits and permissions[] to 2^4 bits (u16). The new code does not enforce that the XWR bits on non-execonly processors have their R bit set, even when running nested: none of the shadow_*_mask values have bit 0 set, and make_spte() genuinely relies on ACC_READ_MASK being requested! This works becase, if execonly is not supported by the processor, shadow EPT will generate an EPT misconfig vmexit if the XWR bits represent a non-readable page, and therefore the pte_access argument to make_spte() will also always have ACC_READ_MASK set. Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/kvm_host.h | 12 +++++----- arch/x86/kvm/mmu.h | 2 +- arch/x86/kvm/mmu/mmu.c | 39 +++++++++++++++++++++------------ arch/x86/kvm/mmu/mmutrace.h | 3 ++- arch/x86/kvm/mmu/paging_tmpl.h | 35 +++++++++++++++++------------ arch/x86/kvm/mmu/spte.c | 18 ++++++--------- arch/x86/kvm/mmu/spte.h | 5 +++-- arch/x86/kvm/vmx/capabilities.h | 5 ----- arch/x86/kvm/vmx/common.h | 5 +---- arch/x86/kvm/vmx/vmx.c | 3 +-- 10 files changed, 67 insertions(+), 60 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 6e4e3ef9b8c7..65671d3769f0 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -327,11 +327,11 @@ struct kvm_kernel_irq_routing_entry; * the number of unique SPs that can theoretically be created is 2^n, wher= e n * is the number of bits that are used to compute the role. * - * But, even though there are 20 bits in the mask below, not all combinati= ons + * But, even though there are 21 bits in the mask below, not all combinati= ons * of modes and flags are possible: * * - invalid shadow pages are not accounted, mirror pages are not shadow= ed, - * so the bits are effectively 18. + * so the bits are effectively 19. * * - quadrant will only be used if has_4_byte_gpte=3D1 (non-PAE paging); * execonly and ad_disabled are only used for nested EPT which has @@ -346,7 +346,7 @@ struct kvm_kernel_irq_routing_entry; * cr0_wp=3D0, therefore these three bits only give rise to 5 possibil= ities. * * Therefore, the maximum number of possible upper-level shadow pages for a - * single gfn is a bit less than 2^13. + * single gfn is a bit less than 2^14. */ union kvm_mmu_page_role { u32 word; @@ -355,7 +355,7 @@ union kvm_mmu_page_role { unsigned has_4_byte_gpte:1; unsigned quadrant:2; unsigned direct:1; - unsigned access:3; + unsigned access:4; unsigned invalid:1; unsigned efer_nx:1; unsigned cr0_wp:1; @@ -365,7 +365,7 @@ union kvm_mmu_page_role { unsigned guest_mode:1; unsigned passthrough:1; unsigned is_mirror:1; - unsigned :4; + unsigned:3; =20 /* * This is left at the top of the word so that @@ -491,7 +491,7 @@ struct kvm_mmu { * Byte index: page fault error code [4:1] * Bit index: pte permissions in ACC_* format */ - u8 permissions[16]; + u16 permissions[16]; =20 u64 *pae_root; u64 *pml4_root; diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 830f46145692..23f37535c0ce 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -81,7 +81,7 @@ u8 kvm_mmu_get_max_tdp_level(void); void kvm_mmu_set_mmio_spte_mask(u64 mmio_value, u64 mmio_mask, u64 access_= mask); void kvm_mmu_set_mmio_spte_value(struct kvm *kvm, u64 mmio_value); void kvm_mmu_set_me_spte_mask(u64 me_value, u64 me_mask); -void kvm_mmu_set_ept_masks(bool has_ad_bits, bool has_exec_only); +void kvm_mmu_set_ept_masks(bool has_ad_bits); =20 void kvm_init_mmu(struct kvm_vcpu *vcpu); void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, unsigned long cr0, diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 170952a840db..5f578435b5ad 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -2033,7 +2033,7 @@ static bool kvm_sync_page_check(struct kvm_vcpu *vcpu= , struct kvm_mmu_page *sp) */ const union kvm_mmu_page_role sync_role_ign =3D { .level =3D 0xf, - .access =3D 0x7, + .access =3D ACC_ALL, .quadrant =3D 0x3, .passthrough =3D 0x1, }; @@ -5527,7 +5527,7 @@ reset_ept_shadow_zero_bits_mask(struct kvm_mmu *conte= xt, bool execonly) * update_permission_bitmask() builds what is effectively a * two-dimensional array of bools. The second dimension is * provided by individual bits of permissions[pfec >> 1], and - * logical &, | and ~ operations operate on all the 8 possible + * logical &, | and ~ operations operate on all the 16 possible * combinations of ACC_* bits. */ #define ACC_BITS_MASK(access) \ @@ -5537,15 +5537,24 @@ reset_ept_shadow_zero_bits_mask(struct kvm_mmu *con= text, bool execonly) (4 & (access) ? 1 << 4 : 0) | \ (5 & (access) ? 1 << 5 : 0) | \ (6 & (access) ? 1 << 6 : 0) | \ - (7 & (access) ? 1 << 7 : 0)) + (7 & (access) ? 1 << 7 : 0) | \ + (8 & (access) ? 1 << 8 : 0) | \ + (9 & (access) ? 1 << 9 : 0) | \ + (10 & (access) ? 1 << 10 : 0) | \ + (11 & (access) ? 1 << 11 : 0) | \ + (12 & (access) ? 1 << 12 : 0) | \ + (13 & (access) ? 1 << 13 : 0) | \ + (14 & (access) ? 1 << 14 : 0) | \ + (15 & (access) ? 1 << 15 : 0)) =20 static void update_permission_bitmask(struct kvm_mmu *mmu, bool ept) { unsigned byte; =20 - const u8 x =3D ACC_BITS_MASK(ACC_EXEC_MASK); - const u8 w =3D ACC_BITS_MASK(ACC_WRITE_MASK); - const u8 u =3D ACC_BITS_MASK(ACC_USER_MASK); + const u16 x =3D ACC_BITS_MASK(ACC_EXEC_MASK); + const u16 w =3D ACC_BITS_MASK(ACC_WRITE_MASK); + const u16 u =3D ACC_BITS_MASK(ACC_USER_MASK); + const u16 r =3D ACC_BITS_MASK(ACC_READ_MASK); =20 bool cr4_smep =3D is_cr4_smep(mmu); bool cr4_smap =3D is_cr4_smap(mmu); @@ -5568,24 +5577,26 @@ static void update_permission_bitmask(struct kvm_mm= u *mmu, bool ept) unsigned pfec =3D byte << 1; =20 /* - * Each "*f" variable has a 1 bit for each UWX value + * Each "*f" variable has a 1 bit for each ACC_* combo * that causes a fault with the given PFEC. */ =20 + /* Faults from reads to non-readable pages */ + u16 rf =3D (pfec & (PFERR_WRITE_MASK|PFERR_FETCH_MASK)) ? 0 : (u16)~r; /* Faults from writes to non-writable pages */ - u8 wf =3D (pfec & PFERR_WRITE_MASK) ? (u8)~w : 0; + u16 wf =3D (pfec & PFERR_WRITE_MASK) ? (u16)~w : 0; /* Faults from user mode accesses to supervisor pages */ - u8 uf =3D (pfec & PFERR_USER_MASK) ? (u8)~u : 0; + u16 uf =3D (pfec & PFERR_USER_MASK) ? (u16)~u : 0; /* Faults from fetches of non-executable pages*/ - u8 ff =3D (pfec & PFERR_FETCH_MASK) ? (u8)~x : 0; + u16 ff =3D (pfec & PFERR_FETCH_MASK) ? (u16)~x : 0; /* Faults from kernel mode fetches of user pages */ - u8 smepf =3D 0; + u16 smepf =3D 0; /* Faults from kernel mode accesses of user pages */ - u8 smapf =3D 0; + u16 smapf =3D 0; =20 if (!ept) { /* Faults from kernel mode accesses to user pages */ - u8 kf =3D (pfec & PFERR_USER_MASK) ? 0 : u; + u16 kf =3D (pfec & PFERR_USER_MASK) ? 0 : u; =20 /* Not really needed: !nx will cause pte.nx to fault */ if (!efer_nx) @@ -5618,7 +5629,7 @@ static void update_permission_bitmask(struct kvm_mmu = *mmu, bool ept) smapf =3D (pfec & (PFERR_RSVD_MASK|PFERR_FETCH_MASK)) ? 0 : kf; } =20 - mmu->permissions[byte] =3D ff | uf | wf | smepf | smapf; + mmu->permissions[byte] =3D ff | uf | wf | rf | smepf | smapf; } } =20 diff --git a/arch/x86/kvm/mmu/mmutrace.h b/arch/x86/kvm/mmu/mmutrace.h index 764e3015d021..dcfdfedfc4e9 100644 --- a/arch/x86/kvm/mmu/mmutrace.h +++ b/arch/x86/kvm/mmu/mmutrace.h @@ -25,7 +25,8 @@ #define KVM_MMU_PAGE_PRINTK() ({ \ const char *saved_ptr =3D trace_seq_buffer_ptr(p); \ static const char *access_str[] =3D { \ - "---", "--x", "w--", "w-x", "-u-", "-ux", "wu-", "wux" \ + "----", "r---", "-w--", "rw--", "--u-", "r-u-", "-wu-", "rwu-", \ + "---x", "r--x", "-w-x", "rw-x", "--ux", "r-ux", "-wux", "rwux" \ }; \ union kvm_mmu_page_role role; \ \ diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h index 901cd2bd40b8..fb1b5d8b23e5 100644 --- a/arch/x86/kvm/mmu/paging_tmpl.h +++ b/arch/x86/kvm/mmu/paging_tmpl.h @@ -170,25 +170,24 @@ static bool FNAME(prefetch_invalid_gpte)(struct kvm_v= cpu *vcpu, return true; } =20 -/* - * For PTTYPE_EPT, a page table can be executable but not readable - * on supported processors. Therefore, set_spte does not automatically - * set bit 0 if execute only is supported. Here, we repurpose ACC_USER_MASK - * to signify readability since it isn't used in the EPT case - */ static inline unsigned FNAME(gpte_access)(u64 gpte) { unsigned access; #if PTTYPE =3D=3D PTTYPE_EPT access =3D ((gpte & VMX_EPT_WRITABLE_MASK) ? ACC_WRITE_MASK : 0) | ((gpte & VMX_EPT_EXECUTABLE_MASK) ? ACC_EXEC_MASK : 0) | - ((gpte & VMX_EPT_READABLE_MASK) ? ACC_USER_MASK : 0); + ((gpte & VMX_EPT_READABLE_MASK) ? ACC_READ_MASK : 0); #else - BUILD_BUG_ON(ACC_EXEC_MASK !=3D PT_PRESENT_MASK); - BUILD_BUG_ON(ACC_EXEC_MASK !=3D 1); + /* + * P is set here, so the page is always readable and W/U/!NX represent + * allowed accesses. + */ + BUILD_BUG_ON(ACC_READ_MASK !=3D PT_PRESENT_MASK); + BUILD_BUG_ON(ACC_WRITE_MASK !=3D PT_WRITABLE_MASK); + BUILD_BUG_ON(ACC_USER_MASK !=3D PT_USER_MASK); + BUILD_BUG_ON(ACC_EXEC_MASK & (PT_WRITABLE_MASK | PT_USER_MASK | PT_PRESEN= T_MASK)); access =3D gpte & (PT_WRITABLE_MASK | PT_USER_MASK | PT_PRESENT_MASK); - /* Combine NX with P (which is set here) to get ACC_EXEC_MASK. */ - access ^=3D (gpte >> PT64_NX_SHIFT); + access |=3D gpte & PT64_NX_MASK ? 0 : ACC_EXEC_MASK; #endif =20 return access; @@ -501,10 +500,18 @@ static int FNAME(walk_addr_generic)(struct guest_walk= er *walker, =20 if (write_fault) walker->fault.exit_qualification |=3D EPT_VIOLATION_ACC_WRITE; - if (user_fault) - walker->fault.exit_qualification |=3D EPT_VIOLATION_ACC_READ; - if (fetch_fault) + else if (fetch_fault) walker->fault.exit_qualification |=3D EPT_VIOLATION_ACC_INSTR; + else + walker->fault.exit_qualification |=3D EPT_VIOLATION_ACC_READ; + + /* + * Accesses to guest paging structures are either "reads" or + * "read+write" accesses, so consider them the latter if write_fault + * is true. + */ + if (access & PFERR_GUEST_PAGE_MASK) + walker->fault.exit_qualification |=3D EPT_VIOLATION_ACC_READ; =20 /* * Note, pte_access holds the raw RWX bits from the EPTE, not diff --git a/arch/x86/kvm/mmu/spte.c b/arch/x86/kvm/mmu/spte.c index e9dc0ae44274..7b5f118ae211 100644 --- a/arch/x86/kvm/mmu/spte.c +++ b/arch/x86/kvm/mmu/spte.c @@ -194,12 +194,6 @@ bool make_spte(struct kvm_vcpu *vcpu, struct kvm_mmu_p= age *sp, int is_host_mmio =3D -1; bool wrprot =3D false; =20 - /* - * For the EPT case, shadow_present_mask has no RWX bits set if - * exec-only page table entries are supported. In that case, - * ACC_USER_MASK and shadow_user_mask are used to represent - * read access. See FNAME(gpte_access) in paging_tmpl.h. - */ WARN_ON_ONCE((pte_access | shadow_present_mask) =3D=3D SHADOW_NONPRESENT_= VALUE); =20 if (sp->role.ad_disabled) @@ -228,6 +222,9 @@ bool make_spte(struct kvm_vcpu *vcpu, struct kvm_mmu_pa= ge *sp, pte_access &=3D ~ACC_EXEC_MASK; } =20 + if (pte_access & ACC_READ_MASK) + spte |=3D PT_PRESENT_MASK; /* or VMX_EPT_READABLE_MASK */ + if (pte_access & ACC_EXEC_MASK) spte |=3D shadow_x_mask; else @@ -391,6 +388,7 @@ u64 make_nonleaf_spte(u64 *child_pt, bool ad_disabled) u64 spte =3D SPTE_MMU_PRESENT_MASK; =20 spte |=3D __pa(child_pt) | shadow_present_mask | PT_WRITABLE_MASK | + PT_PRESENT_MASK /* or VMX_EPT_READABLE_MASK */ | shadow_user_mask | shadow_x_mask | shadow_me_value; =20 if (ad_disabled) @@ -491,18 +489,16 @@ void kvm_mmu_set_me_spte_mask(u64 me_value, u64 me_ma= sk) } EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_mmu_set_me_spte_mask); =20 -void kvm_mmu_set_ept_masks(bool has_ad_bits, bool has_exec_only) +void kvm_mmu_set_ept_masks(bool has_ad_bits) { kvm_ad_enabled =3D has_ad_bits; =20 - shadow_user_mask =3D VMX_EPT_READABLE_MASK; + shadow_user_mask =3D 0; shadow_accessed_mask =3D VMX_EPT_ACCESS_BIT; shadow_dirty_mask =3D VMX_EPT_DIRTY_BIT; shadow_nx_mask =3D 0ull; shadow_x_mask =3D VMX_EPT_EXECUTABLE_MASK; - /* VMX_EPT_SUPPRESS_VE_BIT is needed for W or X violation. */ - shadow_present_mask =3D - (has_exec_only ? 0ull : VMX_EPT_READABLE_MASK) | VMX_EPT_SUPPRESS_VE_BIT; + shadow_present_mask =3D VMX_EPT_SUPPRESS_VE_BIT; =20 shadow_acc_track_mask =3D VMX_EPT_RWX_MASK; shadow_host_writable_mask =3D EPT_SPTE_HOST_WRITABLE; diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h index bc02a2e89a31..121bfb2217e8 100644 --- a/arch/x86/kvm/mmu/spte.h +++ b/arch/x86/kvm/mmu/spte.h @@ -52,10 +52,11 @@ static_assert(SPTE_TDP_AD_ENABLED =3D=3D 0); #define SPTE_BASE_ADDR_MASK (((1ULL << 52) - 1) & ~(u64)(PAGE_SIZE-1)) #endif =20 -#define ACC_EXEC_MASK 1 +#define ACC_READ_MASK PT_PRESENT_MASK #define ACC_WRITE_MASK PT_WRITABLE_MASK #define ACC_USER_MASK PT_USER_MASK -#define ACC_ALL (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK) +#define ACC_EXEC_MASK 8 +#define ACC_ALL (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK |= ACC_READ_MASK) =20 #define SPTE_LEVEL_BITS 9 #define SPTE_LEVEL_SHIFT(level) __PT_LEVEL_SHIFT(level, SPTE_LEVEL_BITS) diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilitie= s.h index 4e371c93ae16..609477f190e8 100644 --- a/arch/x86/kvm/vmx/capabilities.h +++ b/arch/x86/kvm/vmx/capabilities.h @@ -300,11 +300,6 @@ static inline bool cpu_has_vmx_flexpriority(void) cpu_has_vmx_virtualize_apic_accesses(); } =20 -static inline bool cpu_has_vmx_ept_execute_only(void) -{ - return vmx_capability.ept & VMX_EPT_EXECUTE_ONLY_BIT; -} - static inline bool cpu_has_vmx_ept_4levels(void) { return vmx_capability.ept & VMX_EPT_PAGE_WALK_4_BIT; diff --git a/arch/x86/kvm/vmx/common.h b/arch/x86/kvm/vmx/common.h index adf925500b9e..1afbf272efae 100644 --- a/arch/x86/kvm/vmx/common.h +++ b/arch/x86/kvm/vmx/common.h @@ -85,11 +85,8 @@ static inline int __vmx_handle_ept_violation(struct kvm_= vcpu *vcpu, gpa_t gpa, { u64 error_code; =20 - /* Is it a read fault? */ - error_code =3D (exit_qualification & EPT_VIOLATION_ACC_READ) - ? PFERR_USER_MASK : 0; /* Is it a write fault? */ - error_code |=3D (exit_qualification & EPT_VIOLATION_ACC_WRITE) + error_code =3D (exit_qualification & EPT_VIOLATION_ACC_WRITE) ? PFERR_WRITE_MASK : 0; /* Is it a fetch fault? */ error_code |=3D (exit_qualification & EPT_VIOLATION_ACC_INSTR) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 8b24e682535b..e27868fa4eb7 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -8798,8 +8798,7 @@ __init int vmx_hardware_setup(void) set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */ =20 if (enable_ept) - kvm_mmu_set_ept_masks(enable_ept_ad_bits, - cpu_has_vmx_ept_execute_only()); + kvm_mmu_set_ept_masks(enable_ept_ad_bits); else vt_x86_ops.get_mt_mask =3D NULL; =20 --=20 2.53.0