From: Claudio Imbrenda <imbrenda@linux.ibm.com>
To: kvm@vger.kernel.org
Cc: linux-s390@vger.kernel.org, borntraeger@de.ibm.com,
frankja@linux.ibm.com, nsg@linux.ibm.com, nrb@linux.ibm.com,
seiden@linux.ibm.com, schlameuss@linux.ibm.com,
hca@linux.ibm.com, svens@linux.ibm.com, agordeev@linux.ibm.com,
david@redhat.com, gerald.schaefer@linux.ibm.com
Subject: [PATCH v2 11/20] KVM: s390: KVM page table management functions: storage keys
Date: Wed, 10 Sep 2025 20:07:37 +0200 [thread overview]
Message-ID: <20250910180746.125776-12-imbrenda@linux.ibm.com> (raw)
In-Reply-To: <20250910180746.125776-1-imbrenda@linux.ibm.com>
Add page table management functions to be used for KVM guest (gmap)
page tables.
This patch adds functions related to storage key handling.
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
---
arch/s390/kvm/dat.c | 212 ++++++++++++++++++++++++++++++++++++++++++++
arch/s390/kvm/dat.h | 6 ++
2 files changed, 218 insertions(+)
diff --git a/arch/s390/kvm/dat.c b/arch/s390/kvm/dat.c
index fe93e1c07158..f626e8c37770 100644
--- a/arch/s390/kvm/dat.c
+++ b/arch/s390/kvm/dat.c
@@ -560,3 +560,215 @@ long _dat_walk_gfn_range(gfn_t start, gfn_t end, union asce asce,
return dat_crste_walk_range(start, min(end, asce_end(asce)), table, &walk);
}
+
+int dat_get_storage_key(union asce asce, gfn_t gfn, union skey *skey)
+{
+ union crste *crstep;
+ union pgste pgste;
+ union pte *ptep;
+ int rc;
+
+ skey->skey = 0;
+ rc = dat_entry_walk(gfn, asce, DAT_WALK_ANY, LEVEL_PTE, &crstep, &ptep);
+ if (rc)
+ return rc;
+
+ if (!ptep) {
+ union crste crste;
+
+ crste = READ_ONCE(*crstep);
+ if (!crste.h.fc || !crste.s.fc1.pr)
+ return 0;
+ skey->skey = page_get_storage_key(large_crste_to_phys(crste, gfn));
+ return 0;
+ }
+ pgste = pgste_get_lock(ptep);
+ if (ptep->h.i) {
+ skey->acc = pgste.acc;
+ skey->fp = pgste.fp;
+ } else {
+ skey->skey = page_get_storage_key(pte_origin(*ptep));
+ }
+ skey->r |= pgste.gr;
+ skey->c |= pgste.gc;
+ pgste_set_unlock(ptep, pgste);
+ return 0;
+}
+
+static void dat_update_ptep_sd(union pgste old, union pgste pgste, union pte *ptep)
+{
+ if (pgste.acc != old.acc || pgste.fp != old.fp || pgste.gr != old.gr || pgste.gc != old.gc)
+ __atomic64_or(_PAGE_SD, &ptep->val);
+}
+
+int dat_set_storage_key(union asce asce, gfn_t gfn, union skey skey, bool nq)
+{
+ union pgste pgste, old;
+ union crste *crstep;
+ union pte *ptep;
+ int rc;
+
+ rc = dat_entry_walk(gfn, asce, DAT_WALK_LEAF_ALLOC, LEVEL_PTE, &crstep, &ptep);
+ if (rc)
+ return rc;
+
+ if (!ptep) {
+ page_set_storage_key(large_crste_to_phys(*crstep, gfn), skey.skey, !nq);
+ return 0;
+ }
+
+ old = pgste_get_lock(ptep);
+ pgste = old;
+
+ pgste.acc = skey.acc;
+ pgste.fp = skey.fp;
+ pgste.gc = skey.c;
+ pgste.gr = skey.r;
+
+ if (!ptep->h.i) {
+ union skey old_skey;
+
+ old_skey.skey = page_get_storage_key(pte_origin(*ptep));
+ pgste.hc |= old_skey.c;
+ pgste.hr |= old_skey.r;
+ skey.r = 0;
+ skey.c = 0;
+ page_set_storage_key(pte_origin(*ptep), skey.skey, !nq);
+ }
+
+ dat_update_ptep_sd(old, pgste, ptep);
+ pgste_set_unlock(ptep, pgste);
+ return 0;
+}
+
+static bool page_cond_set_storage_key(phys_addr_t paddr, union skey skey, union skey *oldkey,
+ bool nq, bool mr, bool mc)
+{
+ oldkey->skey = page_get_storage_key(paddr);
+ if (oldkey->acc == skey.acc && oldkey->fp == skey.fp &&
+ (oldkey->r == skey.r || mr) && (oldkey->c == skey.c || mc))
+ return false;
+ page_set_storage_key(paddr, skey.skey, !nq);
+ return true;
+}
+
+int dat_cond_set_storage_key(union asce asce, gfn_t gfn, union skey skey, union skey *oldkey,
+ bool nq, bool mr, bool mc)
+{
+ union pgste pgste, old;
+ union crste *crstep;
+ union pte *ptep;
+ int rc;
+
+ rc = dat_entry_walk(gfn, asce, DAT_WALK_LEAF_ALLOC, LEVEL_PTE, &crstep, &ptep);
+ if (rc)
+ return rc;
+
+ if (!ptep)
+ return page_cond_set_storage_key(large_crste_to_phys(*crstep, gfn), skey, oldkey,
+ nq, mr, mc);
+
+ old = pgste_get_lock(ptep);
+ pgste = old;
+
+ rc = 1;
+ pgste.acc = skey.acc;
+ pgste.fp = skey.fp;
+ pgste.gc = skey.c;
+ pgste.gr = skey.r;
+
+ if (!ptep->h.i) {
+ union skey prev;
+
+ rc = page_cond_set_storage_key(pte_origin(*ptep), skey, &prev, nq, mr, mc);
+ pgste.hc |= prev.c;
+ pgste.hr |= prev.r;
+ if (oldkey)
+ *oldkey = prev;
+ }
+
+ dat_update_ptep_sd(old, pgste, ptep);
+ pgste_set_unlock(ptep, pgste);
+ return rc;
+}
+
+int dat_reset_reference_bit(union asce asce, gfn_t gfn)
+{
+ union pgste pgste, old;
+ union crste *crstep;
+ union pte *ptep;
+ int rc;
+
+ rc = dat_entry_walk(gfn, asce, DAT_WALK_ANY, LEVEL_PTE, &crstep, &ptep);
+ if (rc)
+ return rc;
+
+ if (!ptep) {
+ union crste crste = READ_ONCE(*crstep);
+
+ if (!crste.h.fc || !crste.s.fc1.pr)
+ return 0;
+ return page_reset_referenced(large_crste_to_phys(*crstep, gfn));
+ }
+ old = pgste_get_lock(ptep);
+ pgste = old;
+
+ if (!ptep->h.i) {
+ rc = page_reset_referenced(pte_origin(*ptep));
+ pgste.hr = rc >> 1;
+ }
+ rc |= (pgste.gr << 1) | pgste.gc;
+ pgste.gr = 0;
+
+ dat_update_ptep_sd(old, pgste, ptep);
+ pgste_set_unlock(ptep, pgste);
+ return rc;
+}
+
+static long dat_reset_skeys_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
+{
+ union pgste pgste;
+
+ pgste = pgste_get_lock(ptep);
+ pgste.acc = 0;
+ pgste.fp = 0;
+ pgste.gr = 0;
+ pgste.gc = 0;
+ if (ptep->s.pr)
+ page_set_storage_key(pte_origin(*ptep), PAGE_DEFAULT_KEY, 1);
+ pgste_set_unlock(ptep, pgste);
+
+ if (need_resched())
+ return next;
+ return 0;
+}
+
+static long dat_reset_skeys_crste(union crste *crstep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
+{
+ phys_addr_t addr, end, origin = crste_origin_large(*crstep);
+
+ if (!crstep->h.fc || !crstep->s.fc1.pr)
+ return 0;
+
+ addr = ((max(gfn, walk->start) - gfn) << PAGE_SHIFT) + origin;
+ end = ((min(next, walk->end) - gfn) << PAGE_SHIFT) + origin;
+ while (ALIGN(addr + 1, _SEGMENT_SIZE) <= end)
+ addr = sske_frame(addr, PAGE_DEFAULT_KEY);
+ for ( ; addr < end; addr += PAGE_SIZE)
+ page_set_storage_key(addr, PAGE_DEFAULT_KEY, 1);
+
+ if (need_resched())
+ return next;
+ return 0;
+}
+
+long dat_reset_skeys(union asce asce, gfn_t start)
+{
+ const struct dat_walk_ops ops = {
+ .pte_entry = dat_reset_skeys_pte,
+ .pmd_entry = dat_reset_skeys_crste,
+ .pud_entry = dat_reset_skeys_crste,
+ };
+
+ return _dat_walk_gfn_range(start, asce_end(asce), asce, &ops, DAT_WALK_IGN_HOLES, NULL);
+}
diff --git a/arch/s390/kvm/dat.h b/arch/s390/kvm/dat.h
index de4bd2298945..40f5c1371ef3 100644
--- a/arch/s390/kvm/dat.h
+++ b/arch/s390/kvm/dat.h
@@ -427,6 +427,12 @@ int dat_entry_walk(gfn_t gfn, union asce asce, int flags, int walk_level,
void dat_free_level(struct crst_table *table, bool owns_ptes);
struct page_table *dat_alloc_pt(unsigned long pte_bits, unsigned long pgste_bits);
struct crst_table *dat_alloc_crst(unsigned long init);
+int dat_get_storage_key(union asce asce, gfn_t gfn, union skey *skey);
+int dat_set_storage_key(union asce asce, gfn_t gfn, union skey skey, bool nq);
+int dat_cond_set_storage_key(union asce asce, gfn_t gfn, union skey skey, union skey *oldkey,
+ bool nq, bool mr, bool mc);
+int dat_reset_reference_bit(union asce asce, gfn_t gfn);
+long dat_reset_skeys(union asce asce, gfn_t start);
static inline struct crst_table *crste_table_start(union crste *crstep)
{
--
2.51.0
next prev parent reply other threads:[~2025-09-10 18:07 UTC|newest]
Thread overview: 75+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-10 18:07 [PATCH v2 00/20] KVM: s390: gmap rewrite, the real deal Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 01/20] KVM: s390: add P bit in table entry bitfields, move union vaddress Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 02/20] s390: Move sske_frame() to a header Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 03/20] KVM: s390: Add gmap_helper_set_unused() Claudio Imbrenda
2025-09-11 8:38 ` Nico Boehr
2025-09-12 9:17 ` Nina Schoetterl-Glausch
2025-09-15 11:33 ` Claudio Imbrenda
2025-10-27 18:00 ` Nina Schoetterl-Glausch
2025-09-10 18:07 ` [PATCH v2 04/20] KVM: s390: Enable KVM_GENERIC_MMU_NOTIFIER Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 05/20] KVM: s390: Add helper functions for fault handling Claudio Imbrenda
2025-09-12 17:56 ` Nina Schoetterl-Glausch
2025-09-15 11:49 ` Claudio Imbrenda
2025-09-18 14:19 ` Alexander Gordeev
2025-09-18 14:46 ` Claudio Imbrenda
2025-09-18 14:41 ` Alexander Gordeev
2025-09-18 15:10 ` Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 06/20] KVM: s390: Rename some functions in gaccess.c Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 07/20] KVM: s390: KVM-specific bitfields and helper functions Claudio Imbrenda
2025-09-17 12:18 ` Heiko Carstens
2025-09-17 12:51 ` Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 08/20] KVM: s390: KVM page table management functions: allocation Claudio Imbrenda
2025-09-11 8:22 ` Janosch Frank
2025-09-11 8:43 ` Claudio Imbrenda
2025-09-16 16:26 ` Heiko Carstens
2025-09-16 16:47 ` Claudio Imbrenda
2025-09-16 17:01 ` Christian Borntraeger
2025-09-16 17:05 ` Claudio Imbrenda
2025-09-16 17:06 ` Christian Borntraeger
2025-09-16 17:36 ` Heiko Carstens
2025-09-17 7:27 ` Heiko Carstens
2025-09-17 11:25 ` Claudio Imbrenda
2025-09-17 12:30 ` Heiko Carstens
2025-09-17 13:11 ` Claudio Imbrenda
2025-09-17 13:26 ` Christian Borntraeger
2025-09-17 14:00 ` Claudio Imbrenda
2025-09-17 14:05 ` Christian Borntraeger
2025-09-17 14:11 ` Claudio Imbrenda
2025-09-17 17:08 ` Claudio Imbrenda
2025-09-17 13:31 ` Heiko Carstens
2025-09-17 14:00 ` Claudio Imbrenda
2025-09-17 12:12 ` Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 09/20] KVM: s390: KVM page table management functions: clear and replace Claudio Imbrenda
2025-09-11 12:57 ` Janosch Frank
2025-09-11 13:19 ` Claudio Imbrenda
2025-09-11 13:27 ` Janosch Frank
2025-09-16 15:56 ` Heiko Carstens
2025-09-16 16:47 ` Heiko Carstens
2025-09-16 17:04 ` Claudio Imbrenda
2025-09-16 17:27 ` Heiko Carstens
2025-09-10 18:07 ` [PATCH v2 10/20] KVM: s390: KVM page table management functions: walks Claudio Imbrenda
2025-09-11 12:56 ` Janosch Frank
2025-09-11 13:14 ` Claudio Imbrenda
2025-09-12 5:47 ` Gerd Bayer
2025-09-16 16:22 ` Heiko Carstens
2025-09-16 16:48 ` Claudio Imbrenda
2025-09-16 17:24 ` Heiko Carstens
2025-09-17 11:14 ` Claudio Imbrenda
2025-09-17 12:55 ` Heiko Carstens
2025-09-17 13:13 ` Claudio Imbrenda
2025-09-17 13:24 ` Heiko Carstens
2025-09-17 14:01 ` Claudio Imbrenda
2025-09-10 18:07 ` Claudio Imbrenda [this message]
2025-09-10 18:07 ` [PATCH v2 12/20] KVM: s390: KVM page table management functions: lifecycle management Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 13/20] KVM: s390: KVM page table management functions: CMMA Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 14/20] KVM: s390: New gmap code Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 15/20] KVM: s390: Stop using CONFIG_PGSTE Claudio Imbrenda
2025-09-16 7:45 ` Steffen Eiden
2025-09-10 18:07 ` [PATCH v2 16/20] KVM: s390: Switch to new gmap Claudio Imbrenda
2025-09-17 13:20 ` Heiko Carstens
2025-09-10 18:07 ` [PATCH v2 17/20] KVM: s390: Remove gmap from s390/mm Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 18/20] KVM: S390: Remove PGSTE code from linux/s390 mm Claudio Imbrenda
2025-09-16 7:30 ` Steffen Eiden
2025-09-16 9:24 ` Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 19/20] KVM: s390: Enable 1M pages for gmap Claudio Imbrenda
2025-09-10 18:07 ` [PATCH v2 20/20] KVM: s390: Storage key manipulation IOCTL Claudio Imbrenda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250910180746.125776-12-imbrenda@linux.ibm.com \
--to=imbrenda@linux.ibm.com \
--cc=agordeev@linux.ibm.com \
--cc=borntraeger@de.ibm.com \
--cc=david@redhat.com \
--cc=frankja@linux.ibm.com \
--cc=gerald.schaefer@linux.ibm.com \
--cc=hca@linux.ibm.com \
--cc=kvm@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=nrb@linux.ibm.com \
--cc=nsg@linux.ibm.com \
--cc=schlameuss@linux.ibm.com \
--cc=seiden@linux.ibm.com \
--cc=svens@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox