Skip to content

Commit

Permalink
KVM: S390: Create helper function get_guest_storage_key
Browse files Browse the repository at this point in the history
Define get_guest_storage_key which can be used to get the value of a guest
storage key. This compliments the functionality provided by the helper function
set_guest_storage_key. Both functions are needed for live migration of s390
guests that use storage keys.

Signed-off-by: Jason J. Herne <jjherne@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
  • Loading branch information
Jason J. Herne authored and Christian Borntraeger committed Nov 28, 2014
1 parent da00fcb commit 9fcf93b
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/s390/include/asm/pgalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ void page_table_reset_pgste(struct mm_struct *, unsigned long, unsigned long,
bool init_skey);
int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
unsigned long key, bool nq);
unsigned long get_guest_storage_key(struct mm_struct *mm, unsigned long addr);

static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
{
Expand Down
39 changes: 39 additions & 0 deletions arch/s390/mm/pgtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,45 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
}
EXPORT_SYMBOL(set_guest_storage_key);

unsigned long get_guest_storage_key(struct mm_struct *mm, unsigned long addr)
{
spinlock_t *ptl;
pgste_t pgste;
pte_t *ptep;
uint64_t physaddr;
unsigned long key = 0;

down_read(&mm->mmap_sem);
ptep = get_locked_pte(mm, addr, &ptl);
if (unlikely(!ptep)) {
up_read(&mm->mmap_sem);
return -EFAULT;
}
pgste = pgste_get_lock(ptep);

if (pte_val(*ptep) & _PAGE_INVALID) {
key |= (pgste_val(pgste) & PGSTE_ACC_BITS) >> 56;
key |= (pgste_val(pgste) & PGSTE_FP_BIT) >> 56;
key |= (pgste_val(pgste) & PGSTE_GR_BIT) >> 48;
key |= (pgste_val(pgste) & PGSTE_GC_BIT) >> 48;
} else {
physaddr = pte_val(*ptep) & PAGE_MASK;
key = page_get_storage_key(physaddr);

/* Reflect guest's logical view, not physical */
if (pgste_val(pgste) & PGSTE_GR_BIT)
key |= _PAGE_REFERENCED;
if (pgste_val(pgste) & PGSTE_GC_BIT)
key |= _PAGE_CHANGED;
}

pgste_set_unlock(ptep, pgste);
pte_unmap_unlock(ptep, ptl);
up_read(&mm->mmap_sem);
return key;
}
EXPORT_SYMBOL(get_guest_storage_key);

#else /* CONFIG_PGSTE */

static inline int page_table_with_pgste(struct page *page)
Expand Down

0 comments on commit 9fcf93b

Please sign in to comment.