mirror of
https://github.com/torvalds/linux.git
synced 2026-05-21 21:37:25 +02:00
KVM: s390: move gmap_shadow_pgt_lookup() into kvm
Move gmap_shadow_pgt_lookup() from mm/gmap.c into kvm/gaccess.c . Reviewed-by: Steffen Eiden <seiden@linux.ibm.com> Reviewed-by: Janosch Frank <frankja@linux.ibm.com> Reviewed-by: Christoph Schlameuss <schlameuss@linux.ibm.com> Link: https://lore.kernel.org/r/20250123144627.312456-13-imbrenda@linux.ibm.com Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com> Message-ID: <20250123144627.312456-13-imbrenda@linux.ibm.com>
This commit is contained in:
parent
ef0c8ef848
commit
43656f774a
|
|
@ -125,8 +125,6 @@ int gmap_shadow_sgt(struct gmap *sg, unsigned long saddr, unsigned long sgt,
|
|||
int fake);
|
||||
int gmap_shadow_pgt(struct gmap *sg, unsigned long saddr, unsigned long pgt,
|
||||
int fake);
|
||||
int gmap_shadow_pgt_lookup(struct gmap *sg, unsigned long saddr,
|
||||
unsigned long *pgt, int *dat_protection, int *fake);
|
||||
int gmap_shadow_page(struct gmap *sg, unsigned long saddr, pte_t pte);
|
||||
|
||||
void gmap_register_pte_notifier(struct gmap_notifier *);
|
||||
|
|
@ -142,6 +140,7 @@ void s390_uv_destroy_pfns(unsigned long count, unsigned long *pfns);
|
|||
int __s390_uv_destroy_range(struct mm_struct *mm, unsigned long start,
|
||||
unsigned long end, bool interruptible);
|
||||
int kvm_s390_wiggle_split_folio(struct mm_struct *mm, struct folio *folio, bool split);
|
||||
unsigned long *gmap_table_walk(struct gmap *gmap, unsigned long gaddr, int level);
|
||||
|
||||
/**
|
||||
* s390_uv_destroy_range - Destroy a range of pages in the given mm.
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <asm/gmap.h>
|
||||
#include <asm/dat-bits.h>
|
||||
#include "kvm-s390.h"
|
||||
#include "gmap.h"
|
||||
#include "gaccess.h"
|
||||
|
||||
/*
|
||||
|
|
@ -1392,6 +1393,42 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* shadow_pgt_lookup() - find a shadow page table
|
||||
* @sg: pointer to the shadow guest address space structure
|
||||
* @saddr: the address in the shadow aguest address space
|
||||
* @pgt: parent gmap address of the page table to get shadowed
|
||||
* @dat_protection: if the pgtable is marked as protected by dat
|
||||
* @fake: pgt references contiguous guest memory block, not a pgtable
|
||||
*
|
||||
* Returns 0 if the shadow page table was found and -EAGAIN if the page
|
||||
* table was not found.
|
||||
*
|
||||
* Called with sg->mm->mmap_lock in read.
|
||||
*/
|
||||
static int shadow_pgt_lookup(struct gmap *sg, unsigned long saddr, unsigned long *pgt,
|
||||
int *dat_protection, int *fake)
|
||||
{
|
||||
unsigned long *table;
|
||||
struct page *page;
|
||||
int rc;
|
||||
|
||||
spin_lock(&sg->guest_table_lock);
|
||||
table = gmap_table_walk(sg, saddr, 1); /* get segment pointer */
|
||||
if (table && !(*table & _SEGMENT_ENTRY_INVALID)) {
|
||||
/* Shadow page tables are full pages (pte+pgste) */
|
||||
page = pfn_to_page(*table >> PAGE_SHIFT);
|
||||
*pgt = page->index & ~GMAP_SHADOW_FAKE_TABLE;
|
||||
*dat_protection = !!(*table & _SEGMENT_ENTRY_PROTECT);
|
||||
*fake = !!(page->index & GMAP_SHADOW_FAKE_TABLE);
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = -EAGAIN;
|
||||
}
|
||||
spin_unlock(&sg->guest_table_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_s390_shadow_fault - handle fault on a shadow page table
|
||||
* @vcpu: virtual cpu
|
||||
|
|
@ -1415,6 +1452,9 @@ int kvm_s390_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg,
|
|||
int dat_protection, fake;
|
||||
int rc;
|
||||
|
||||
if (KVM_BUG_ON(!gmap_is_shadow(sg), vcpu->kvm))
|
||||
return -EFAULT;
|
||||
|
||||
mmap_read_lock(sg->mm);
|
||||
/*
|
||||
* We don't want any guest-2 tables to change - so the parent
|
||||
|
|
@ -1423,7 +1463,7 @@ int kvm_s390_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg,
|
|||
*/
|
||||
ipte_lock(vcpu->kvm);
|
||||
|
||||
rc = gmap_shadow_pgt_lookup(sg, saddr, &pgt, &dat_protection, &fake);
|
||||
rc = shadow_pgt_lookup(sg, saddr, &pgt, &dat_protection, &fake);
|
||||
if (rc)
|
||||
rc = kvm_s390_shadow_tables(sg, saddr, &pgt, &dat_protection,
|
||||
&fake);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
#ifndef ARCH_KVM_S390_GMAP_H
|
||||
#define ARCH_KVM_S390_GMAP_H
|
||||
|
||||
#define GMAP_SHADOW_FAKE_TABLE 1ULL
|
||||
|
||||
int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb);
|
||||
int gmap_convert_to_secure(struct gmap *gmap, unsigned long gaddr);
|
||||
int gmap_destroy_page(struct gmap *gmap, unsigned long gaddr);
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@
|
|||
|
||||
#define GMAP_SHADOW_FAKE_TABLE 1ULL
|
||||
|
||||
static inline unsigned long *gmap_table_walk(struct gmap *gmap, unsigned long gaddr, int level);
|
||||
|
||||
static struct page *gmap_alloc_crst(void)
|
||||
{
|
||||
struct page *page;
|
||||
|
|
@ -738,8 +736,7 @@ static void gmap_call_notifier(struct gmap *gmap, unsigned long start,
|
|||
*
|
||||
* Note: Can also be called for shadow gmaps.
|
||||
*/
|
||||
static inline unsigned long *gmap_table_walk(struct gmap *gmap,
|
||||
unsigned long gaddr, int level)
|
||||
unsigned long *gmap_table_walk(struct gmap *gmap, unsigned long gaddr, int level)
|
||||
{
|
||||
const int asce_type = gmap->asce & _ASCE_TYPE_MASK;
|
||||
unsigned long *table = gmap->table;
|
||||
|
|
@ -790,6 +787,7 @@ static inline unsigned long *gmap_table_walk(struct gmap *gmap,
|
|||
}
|
||||
return table;
|
||||
}
|
||||
EXPORT_SYMBOL(gmap_table_walk);
|
||||
|
||||
/**
|
||||
* gmap_pte_op_walk - walk the gmap page table, get the page table lock
|
||||
|
|
@ -1744,46 +1742,6 @@ int gmap_shadow_sgt(struct gmap *sg, unsigned long saddr, unsigned long sgt,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(gmap_shadow_sgt);
|
||||
|
||||
/**
|
||||
* gmap_shadow_pgt_lookup - find a shadow page table
|
||||
* @sg: pointer to the shadow guest address space structure
|
||||
* @saddr: the address in the shadow aguest address space
|
||||
* @pgt: parent gmap address of the page table to get shadowed
|
||||
* @dat_protection: if the pgtable is marked as protected by dat
|
||||
* @fake: pgt references contiguous guest memory block, not a pgtable
|
||||
*
|
||||
* Returns 0 if the shadow page table was found and -EAGAIN if the page
|
||||
* table was not found.
|
||||
*
|
||||
* Called with sg->mm->mmap_lock in read.
|
||||
*/
|
||||
int gmap_shadow_pgt_lookup(struct gmap *sg, unsigned long saddr,
|
||||
unsigned long *pgt, int *dat_protection,
|
||||
int *fake)
|
||||
{
|
||||
unsigned long *table;
|
||||
struct page *page;
|
||||
int rc;
|
||||
|
||||
BUG_ON(!gmap_is_shadow(sg));
|
||||
spin_lock(&sg->guest_table_lock);
|
||||
table = gmap_table_walk(sg, saddr, 1); /* get segment pointer */
|
||||
if (table && !(*table & _SEGMENT_ENTRY_INVALID)) {
|
||||
/* Shadow page tables are full pages (pte+pgste) */
|
||||
page = pfn_to_page(*table >> PAGE_SHIFT);
|
||||
*pgt = page->index & ~GMAP_SHADOW_FAKE_TABLE;
|
||||
*dat_protection = !!(*table & _SEGMENT_ENTRY_PROTECT);
|
||||
*fake = !!(page->index & GMAP_SHADOW_FAKE_TABLE);
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = -EAGAIN;
|
||||
}
|
||||
spin_unlock(&sg->guest_table_lock);
|
||||
return rc;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gmap_shadow_pgt_lookup);
|
||||
|
||||
/**
|
||||
* gmap_shadow_pgt - instantiate a shadow page table
|
||||
* @sg: pointer to the shadow guest address space structure
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user