Skip to content

Commit 380d97b

Browse files
Claudio Imbrendaborntraeger
authored andcommitted
KVM: s390: pv: properly handle page flags for protected guests
Introduce variants of the convert and destroy page functions that also clear the PG_arch_1 bit used to mark them as secure pages. The PG_arch_1 flag is always allowed to overindicate; using the new functions introduced here allows to reduce the extent of overindication and thus improve performance. These new functions can only be called on pages for which a reference is already being held. Signed-off-by: Claudio Imbrenda <[email protected]> Reviewed-by: Janosch Frank <[email protected]> Reviewed-by: Christian Borntraeger <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Christian Borntraeger <[email protected]>
1 parent 85f517b commit 380d97b

File tree

4 files changed

+50
-7
lines changed

4 files changed

+50
-7
lines changed

arch/s390/include/asm/pgtable.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,8 +1074,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
10741074
pte_t res;
10751075

10761076
res = ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
1077+
/* At this point the reference through the mapping is still present */
10771078
if (mm_is_protected(mm) && pte_present(res))
1078-
uv_convert_from_secure(pte_val(res) & PAGE_MASK);
1079+
uv_convert_owned_from_secure(pte_val(res) & PAGE_MASK);
10791080
return res;
10801081
}
10811082

@@ -1091,8 +1092,9 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
10911092
pte_t res;
10921093

10931094
res = ptep_xchg_direct(vma->vm_mm, addr, ptep, __pte(_PAGE_INVALID));
1095+
/* At this point the reference through the mapping is still present */
10941096
if (mm_is_protected(vma->vm_mm) && pte_present(res))
1095-
uv_convert_from_secure(pte_val(res) & PAGE_MASK);
1097+
uv_convert_owned_from_secure(pte_val(res) & PAGE_MASK);
10961098
return res;
10971099
}
10981100

@@ -1116,8 +1118,9 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
11161118
} else {
11171119
res = ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
11181120
}
1121+
/* At this point the reference through the mapping is still present */
11191122
if (mm_is_protected(mm) && pte_present(res))
1120-
uv_convert_from_secure(pte_val(res) & PAGE_MASK);
1123+
uv_convert_owned_from_secure(pte_val(res) & PAGE_MASK);
11211124
return res;
11221125
}
11231126

arch/s390/include/asm/uv.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,16 +356,17 @@ static inline int is_prot_virt_host(void)
356356
}
357357

358358
int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb);
359-
int uv_destroy_page(unsigned long paddr);
359+
int uv_destroy_owned_page(unsigned long paddr);
360360
int uv_convert_from_secure(unsigned long paddr);
361+
int uv_convert_owned_from_secure(unsigned long paddr);
361362
int gmap_convert_to_secure(struct gmap *gmap, unsigned long gaddr);
362363

363364
void setup_uv(void);
364365
#else
365366
#define is_prot_virt_host() 0
366367
static inline void setup_uv(void) {}
367368

368-
static inline int uv_destroy_page(unsigned long paddr)
369+
static inline int uv_destroy_owned_page(unsigned long paddr)
369370
{
370371
return 0;
371372
}
@@ -374,6 +375,11 @@ static inline int uv_convert_from_secure(unsigned long paddr)
374375
{
375376
return 0;
376377
}
378+
379+
static inline int uv_convert_owned_from_secure(unsigned long paddr)
380+
{
381+
return 0;
382+
}
377383
#endif
378384

379385
#endif /* _ASM_S390_UV_H */

arch/s390/kernel/uv.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ static int uv_pin_shared(unsigned long paddr)
100100
*
101101
* @paddr: Absolute host address of page to be destroyed
102102
*/
103-
int uv_destroy_page(unsigned long paddr)
103+
static int uv_destroy_page(unsigned long paddr)
104104
{
105105
struct uv_cb_cfs uvcb = {
106106
.header.cmd = UVC_CMD_DESTR_SEC_STOR,
@@ -120,6 +120,22 @@ int uv_destroy_page(unsigned long paddr)
120120
return 0;
121121
}
122122

123+
/*
124+
* The caller must already hold a reference to the page
125+
*/
126+
int uv_destroy_owned_page(unsigned long paddr)
127+
{
128+
struct page *page = phys_to_page(paddr);
129+
int rc;
130+
131+
get_page(page);
132+
rc = uv_destroy_page(paddr);
133+
if (!rc)
134+
clear_bit(PG_arch_1, &page->flags);
135+
put_page(page);
136+
return rc;
137+
}
138+
123139
/*
124140
* Requests the Ultravisor to encrypt a guest page and make it
125141
* accessible to the host for paging (export).
@@ -139,6 +155,22 @@ int uv_convert_from_secure(unsigned long paddr)
139155
return 0;
140156
}
141157

158+
/*
159+
* The caller must already hold a reference to the page
160+
*/
161+
int uv_convert_owned_from_secure(unsigned long paddr)
162+
{
163+
struct page *page = phys_to_page(paddr);
164+
int rc;
165+
166+
get_page(page);
167+
rc = uv_convert_from_secure(paddr);
168+
if (!rc)
169+
clear_bit(PG_arch_1, &page->flags);
170+
put_page(page);
171+
return rc;
172+
}
173+
142174
/*
143175
* Calculate the expected ref_count for a page that would otherwise have no
144176
* further pins. This was cribbed from similar functions in other places in

arch/s390/mm/gmap.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2684,8 +2684,10 @@ static int __s390_reset_acc(pte_t *ptep, unsigned long addr,
26842684
{
26852685
pte_t pte = READ_ONCE(*ptep);
26862686

2687+
/* There is a reference through the mapping */
26872688
if (pte_present(pte))
2688-
WARN_ON_ONCE(uv_destroy_page(pte_val(pte) & PAGE_MASK));
2689+
WARN_ON_ONCE(uv_destroy_owned_page(pte_val(pte) & PAGE_MASK));
2690+
26892691
return 0;
26902692
}
26912693

0 commit comments

Comments
 (0)