From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=148.163.156.1 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792770949; b=x7ORnqc4uOKAoDCThKbr78Db8kEFzQ98//YJbG3Zn8Z1JRXpI2oV0pYgyRwiAtloc+fF 2p6ngyWdt+m00YQweDKzpPbUiukzOH1bLdAFCzadzJ3Tq6lu4O2Yi3hvv0tGzuF+5vQ9J pZsMuHJ9YKG6JO+fOitgil+TtxmOOhFIZdwTyrmCV22PzWfU7ZAptfVKKmKhipYYzSBg3 WJh/DefqF38T6QSxmpfnD8UgLjfQEkXQDRofynWyTiBt4BIvQhysSlzLFAKv4V9WRmQD9 OUZTA5dnFosFXP8O5ZmAbBM3V5ay539MHeyDwfR0qOoPJmbItoV1e4P41LuVFWDK0CQ== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792770949; h=DMARC-Filter:Received:DKIM-Signature:Received:Received:Received: Received:Received:Received:Received:From:To:Cc:Subject:Date: Message-ID:X-Mailer:In-Reply-To:References:MIME-Version: Content-Transfer-Encoding:X-TM-AS-GCONF:X-Proofpoint-GUID: X-Proofpoint-Spam-Info:X-Proofpoint-Spam-Details-Enc: X-Proofpoint-ORIG-GUID:X-Authority-Analysis: X-Proofpoint-Virus-Version:X-Proofpoint-Spam-Details; bh=5knQg0Padf5iWJg0Ad28o+L1RkJc4ZMbk6Z8LRUJOhA=; b=KSjEo2xGiPyvQZK5jOilVsRpjoHf++y9+zM2SvYpI8z7RkAlillTHkX5DA1MkFKuN4lN EZ2TQW8m7ZmFZ2mqYq/8mp36tyRdoLIMPaP7lvxk1HvmGrwT9AsOJx4ahCDI2FxmTG2Bi 2gkZZ+BrnfrSBrZZJQWAR+48E14pvAlnQ26V5w+jtyUjRCwsNCLJvJB2AJlwoMc+t/X33 q7TPL13mGpcxu+Ztu6QmESfotEMIa7MrWbeQ86SpDgcTYAFwDZY6ptuwg37Yt2m5QMkBZ ZsQXIW7Q5gai8re/Ix0TUBGcotBGapkwFJLUVrmb9/wQPAlpfnSMN5ev+IePNBt3CnA== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=ZqVwXhPG; arc=none smtp.remote-ip=148.163.156.1 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B4CFC606A31F; Fri, 23 Oct 2026 15:55:43 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org B4CFC606A31F Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=ZqVwXhPG Received: from pps.filterd (m0360083.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 69NEF5PB3292163; Fri, 23 Oct 2026 15:55:40 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=5knQg0Padf5iWJg0A d28o+L1RkJc4ZMbk6Z8LRUJOhA=; b=ZqVwXhPGmb2wm8nNQkw5WT+7mvH8OAwbV ZDgG967HooxT/as82wSc1tjXEazAde8ZYFAxjkBmxe65FAt5ee5EabWM0n+yLt8u 0E8WzrrZCGvCiME9Ct7bpIJW4u0m5qqioY7DO3FSsvq1A+8i4vAjKP6d1U7vEpz1 bc3tJSJ5lYSGjFJFxzp1rAFojwIRx/It9rXKgXfJhUMnqeM1n/PEwnQkA0PbwdxN eUy92hZOg2tVeviGAdoKeY4paOS9wp+IwJ2uuOlAQOJNHM+s48HLkIDMKUn0fNyK AUBSSrLs4MqRyzamjzePD2aXtEW4UDeGg5xmxjRBfuVa7zE2jqZCA== Received: from ppma13.dal12v.mail.ibm.com (dd.9e.1632.ip4.static.sl-reverse.com [50.22.158.221]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4hdw596693-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 23 Oct 2026 15:55:40 +0000 (GMT) Received: from pps.filterd (ppma13.dal12v.mail.ibm.com [127.0.0.1]) by ppma13.dal12v.mail.ibm.com (8.18.1.11/8.18.1.11) with ESMTP id 69NE65HX1018579; Fri, 23 Oct 2026 15:55:39 GMT Received: from smtprelay02.fra02v.mail.ibm.com ([9.218.2.226]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 4hg5exsa2h-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 23 Oct 2026 15:55:39 +0000 (GMT) Received: from smtpav01.fra02v.mail.ibm.com (smtpav01.fra02v.mail.ibm.com [10.20.54.100]) by smtprelay02.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 69NFtX5I30147042 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 23 Oct 2026 15:55:33 GMT Received: from smtpav01.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6F42120040; Fri, 23 Oct 2026 15:55:33 +0000 (GMT) Received: from smtpav01.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 45C762004D; Fri, 23 Oct 2026 15:55:33 +0000 (GMT) Received: from p-imbrenda.ehn-de.ibm.com (unknown [9.224.75.30]) by smtpav01.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 23 Oct 2026 15:55:33 +0000 (GMT) From: Claudio Imbrenda To: kvm@vger.kernel.org Cc: linux-s390@vger.kernel.org, borntraeger@de.ibm.com, frankja@linux.ibm.com, david@kernel.org, nrb@linux.ibm.com, schlameuss@linux.ibm.com, gra@linux.ibm.com Subject: [PATCH v2 09/10] KVM: s390: vsie: Fix pinning using the wrong flag Date: Fri, 23 Oct 2026 17:55:30 +0200 Message-ID: <20261023155531.206113-10-imbrenda@linux.ibm.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261023155531.206113-1-imbrenda@linux.ibm.com> References: <20261023155531.206113-1-imbrenda@linux.ibm.com> X-Mailing-List: linux-s390@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-TM-AS-GCONF: 00 X-Proofpoint-GUID: yk7iufY5yBWCgFLMf5PLXnq-KCzURbIx X-Proofpoint-Spam-Info: AW1haW4tMjYxMDIzMDA2MSBTYWx0ZWRfX7mxZGSWNbiN6 UVfzItLwTH1CwcFGjzU2OHj53ADnakrDOQ1LF8O1yumJimb2tw9T4nj6FcYQvNcmepEEm5klCwh KgI62/x0JtcwRC/kQ5uJQsi2H9kSmvc= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYxMDIzMDA2MSBTYWx0ZWRfX93Dkvt4aQUUC ERK15e2ErOrOkRUDVV5Sx9Xeg7J9RszcAu2X+5jDtzFeyjQUjGqVwra1lrd7hb4Ws8d99a34BmJ jIlBXPp3iulN/RCK8hiPHeEsZ1lrSByTMd2gG3wqtAtlhgisuVW5qFpjBs2TniE4ABz6RdX0DS+ qf/WUrbvwzNVRU4I01fDOEZ/aabaxHYBqmvHZPNQ4SwsjDmQOfg/Tx65ZrRp5U4yUqIGa4D9dMZ TP2qJb7v0ym2CEIgvsChkUAv3Yc8TGLPZeEAPZ9rvl68mb8465Kt6MNsOTggDo1n+yPota9NH22 NO5fclN5+FMUJsinWCW86RPATaJunYtX0LfcafpiebqndhcOL54OgnAV3w7I4zzBc5fypdCNkZI blcscQs0PauYZsvfZKMTdEl7ekyaVJZLlSKkeqsy75PNFxzw09Hw4xdZWaXjT+m1h9oTSMiSUvE uG2c0PYT1DxOd8pl0bQ== X-Proofpoint-ORIG-GUID: yk7iufY5yBWCgFLMf5PLXnq-KCzURbIx X-Authority-Analysis: v=2.4 cv=Ob4NnRTY c=1 sm=1 tr=0 ts=6adb837c cx=c_pps a=AfN7/Ok6k8XGzOShvHwTGQ==:117 a=AfN7/Ok6k8XGzOShvHwTGQ==:17 a=660iZSQnnn4A:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=iQ6ETzBq9ecOQQE5vZCe:22 a=VnNF1IyMAAAA:8 a=ugznIdUm-YL1OzzZZBQA:9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.138,FMLib:17.12.100.49 definitions=2026-10-23_04,2026-10-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 adultscore=0 phishscore=0 spamscore=0 suspectscore=0 lowpriorityscore=0 clxscore=1015 impostorscore=0 priorityscore=1501 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2610190000 definitions=main-2610230061 When pinning guest memory using pin_blocks(), gfn_to_page() was used, which under the hood uses FOLL_GET, which is the wrong type of flag for memory that is accessed directly by hardware. Fix by using kvm_vcpu_{,un}map(), which uses FOLL_PIN and is the correct thing to do. While technically a bugfix, the previous behaviour can only lead to guest corruption in extremely convoluted test scenarios that cannot happen in real/production systems. Signed-off-by: Claudio Imbrenda --- arch/s390/kvm/s390/vsie.c | 137 ++++++++++++++------------------------ 1 file changed, 50 insertions(+), 87 deletions(-) diff --git a/arch/s390/kvm/s390/vsie.c b/arch/s390/kvm/s390/vsie.c index 3b5c322bf8b4..0a2cd9315e13 100644 --- a/arch/s390/kvm/s390/vsie.c +++ b/arch/s390/kvm/s390/vsie.c @@ -49,20 +49,21 @@ struct vsie_page { /* address of the last reported fault to guest2 */ unsigned long fault_addr; /* 0x0228 */ /* calculated guest addresses of satellite control blocks */ - gpa_t sca_gpa; /* 0x0230 */ - gpa_t itdba_gpa; /* 0x0238 */ - gpa_t gvrd_gpa; /* 0x0240 */ - gpa_t riccbd_gpa; /* 0x0248 */ - gpa_t sdnx_gpa; /* 0x0250 */ + struct kvm_host_map sca_map; /* 0x0230 */ + struct kvm_host_map itdba_map; /* 0x0260 */ + struct kvm_host_map gvrd_map; /* 0x0290 */ + struct kvm_host_map riccbd_map; /* 0x02c0 */ + struct kvm_host_map sdnx_map; /* 0x02f0 */ + struct kvm_host_map scb_map; /* 0x0320 */ /* * guest address of the original SCB. Remains set for free vsie * pages, so we can properly look them up in our addr_to_page * radix tree. */ - gpa_t scb_gpa; /* 0x0258 */ + gpa_t scb_gpa; /* 0x0350 */ /* the shadow gmap in use by the vsie_page */ - struct gmap_cache gmap_cache; /* 0x0260 */ - __u8 reserved[0x06f8 - 0x0278]; /* 0x0278 */ + struct gmap_cache gmap_cache; /* 0x0358 */ + __u8 reserved[0x06f8 - 0x0370]; /* 0x0370 */ struct kvm_s390_crypto_cb crycb; /* 0x06f8 */ __u8 fac[8 + S390_ARCH_FAC_LIST_SIZE_BYTE];/* 0x07f8 */ }; @@ -681,72 +682,45 @@ static int map_prefix(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, struct } /* - * Pin the guest page given by gpa and set hpa to the pinned host address. + * pin_guest_page() - Pin the given guest page and return its hpa. + * @vcpu: the vCPU + * @gpa: the gpa to pin + * @map: the map representing this pinning. + * * Will always be pinned writable. * - * Returns: - 0 on success - * - -EINVAL if the gpa is not valid guest storage + * Returns: - 0 if the gpa is not valid guest storage, + * - The host hpa of the pinned page in case of success */ -static int pin_guest_page(struct kvm *kvm, gpa_t gpa, hpa_t *hpa) +static hpa_t pin_guest_page(struct kvm_vcpu *vcpu, gpa_t gpa, struct kvm_host_map *map) { - struct page *page; - - page = gfn_to_page(kvm, gpa_to_gfn(gpa)); - if (!page) - return -EINVAL; - *hpa = (hpa_t)page_to_phys(page) + (gpa & ~PAGE_MASK); - return 0; -} - -/* Unpins a page previously pinned via pin_guest_page, marking it as dirty. */ -static void unpin_guest_page(struct kvm *kvm, gpa_t gpa, hpa_t hpa) -{ - kvm_release_page_dirty(pfn_to_page(phys_to_pfn(hpa))); - /* mark the page always as dirty for migration */ - mark_page_dirty(kvm, gpa_to_gfn(gpa)); + if (kvm_vcpu_map(vcpu, gpa_to_gfn(gpa), map)) + return 0; + if (!kvm_vcpu_mapped(map)) + return 0; + return (hpa_t)PFN_PHYS(map->pfn) + (gpa & ~PAGE_MASK); } /* unpin all blocks previously pinned by pin_blocks(), marking them dirty */ static void unpin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) { struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s; - hpa_t hpa; - hpa = (u64) scb_s->scaoh << 32 | scb_s->scaol; - if (hpa) { - unpin_guest_page(vcpu->kvm, vsie_page->sca_gpa, hpa); - vsie_page->sca_gpa = 0; - scb_s->scaol = 0; - scb_s->scaoh = 0; - } + kvm_vcpu_unmap(vcpu, &vsie_page->sca_map); + scb_s->scaol = 0; + scb_s->scaoh = 0; - hpa = scb_s->itdba; - if (hpa) { - unpin_guest_page(vcpu->kvm, vsie_page->itdba_gpa, hpa); - vsie_page->itdba_gpa = 0; - scb_s->itdba = 0; - } + kvm_vcpu_unmap(vcpu, &vsie_page->itdba_map); + scb_s->itdba = 0; - hpa = scb_s->gvrd; - if (hpa) { - unpin_guest_page(vcpu->kvm, vsie_page->gvrd_gpa, hpa); - vsie_page->gvrd_gpa = 0; - scb_s->gvrd = 0; - } + kvm_vcpu_unmap(vcpu, &vsie_page->gvrd_map); + scb_s->gvrd = 0; - hpa = scb_s->riccbd; - if (hpa) { - unpin_guest_page(vcpu->kvm, vsie_page->riccbd_gpa, hpa); - vsie_page->riccbd_gpa = 0; - scb_s->riccbd = 0; - } + kvm_vcpu_unmap(vcpu, &vsie_page->riccbd_map); + scb_s->riccbd = 0; - hpa = scb_s->sdnxo; - if (hpa) { - unpin_guest_page(vcpu->kvm, vsie_page->sdnx_gpa, hpa); - vsie_page->sdnx_gpa = 0; - scb_s->sdnxo = 0; - } + kvm_vcpu_unmap(vcpu, &vsie_page->sdnx_map); + scb_s->sdnxo = 0; } /* @@ -783,13 +757,12 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) ((gpa + offsetof(struct bsca_block, cpu[0]) - 1) & PAGE_MASK)) rc = set_validity_icpt(scb_s, 0x003bU); if (!rc) { - rc = pin_guest_page(vcpu->kvm, gpa, &hpa); - if (rc) + hpa = pin_guest_page(vcpu, gpa, &vsie_page->sca_map); + if (!hpa) rc = set_validity_icpt(scb_s, 0x0034U); } - if (rc) + if (rc || !hpa) goto unpin; - vsie_page->sca_gpa = gpa; scb_s->scaoh = (u32)((u64)hpa >> 32); scb_s->scaol = (u32)(u64)hpa; } @@ -801,12 +774,11 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) goto unpin; } /* 256 bytes cannot cross page boundaries */ - rc = pin_guest_page(vcpu->kvm, gpa, &hpa); - if (rc) { + hpa = pin_guest_page(vcpu, gpa, &vsie_page->itdba_map); + if (!hpa) { rc = set_validity_icpt(scb_s, 0x0080U); goto unpin; } - vsie_page->itdba_gpa = gpa; scb_s->itdba = hpa; } @@ -820,12 +792,11 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) * 512 bytes vector registers cannot cross page boundaries * if this block gets bigger, we have to shadow it. */ - rc = pin_guest_page(vcpu->kvm, gpa, &hpa); - if (rc) { + hpa = pin_guest_page(vcpu, gpa, &vsie_page->gvrd_map); + if (!hpa) { rc = set_validity_icpt(scb_s, 0x1310U); goto unpin; } - vsie_page->gvrd_gpa = gpa; scb_s->gvrd = hpa; } @@ -836,13 +807,12 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) goto unpin; } /* 64 bytes cannot cross page boundaries */ - rc = pin_guest_page(vcpu->kvm, gpa, &hpa); - if (rc) { + hpa = pin_guest_page(vcpu, gpa, &vsie_page->riccbd_map); + if (!hpa) { rc = set_validity_icpt(scb_s, 0x0043U); goto unpin; } /* Validity 0x0044 will be checked by SIE */ - vsie_page->riccbd_gpa = gpa; scb_s->riccbd = hpa; } if (((scb_s->ecb & ECB_GS) && !(scb_s->ecd & ECD_HOSTREGMGMT)) || @@ -866,12 +836,11 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) /* Due to alignment rules (checked above) this cannot * cross page boundaries */ - rc = pin_guest_page(vcpu->kvm, gpa, &hpa); - if (rc) { + hpa = pin_guest_page(vcpu, gpa, &vsie_page->sdnx_map); + if (!hpa) { rc = set_validity_icpt(scb_s, 0x10b0U); goto unpin; } - vsie_page->sdnx_gpa = gpa; scb_s->sdnxo = hpa | sdnxc; } return 0; @@ -881,13 +850,9 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) } /* unpin the scb provided by guest 2, marking it as dirty */ -static void unpin_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, - gpa_t gpa) +static void unpin_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) { - hpa_t hpa = virt_to_phys(vsie_page->scb_o); - - if (hpa) - unpin_guest_page(vcpu->kvm, gpa, hpa); + kvm_vcpu_unmap(vcpu, &vsie_page->scb_map); vsie_page->scb_o = NULL; } @@ -901,12 +866,10 @@ static int pin_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, gpa_t gpa) { hpa_t hpa; - int rc; - rc = pin_guest_page(vcpu->kvm, gpa, &hpa); - if (rc) { - rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); - WARN_ON_ONCE(rc); + hpa = pin_guest_page(vcpu, gpa, &vsie_page->scb_map); + if (!hpa) { + WARN_ON_ONCE(kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING)); return 1; } vsie_page->scb_o = phys_to_virt(hpa); @@ -1602,7 +1565,7 @@ int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu) out_unshadow: unshadow_scb(vcpu, vsie_page); out_unpin_scb: - unpin_scb(vcpu, vsie_page, scb_addr); + unpin_scb(vcpu, vsie_page); out_put: put_vsie_page(vsie_page); -- 2.56.0