Skip to content

Commit

Permalink
Merge tag 'kvm-s390-next-4.14-2' of git://git.kernel.org/pub/scm/linu…
Browse files Browse the repository at this point in the history
…x/kernel/git/kvms390/linux

KVM: s390: Fixes and features for 4.14

- merge of topic branch tlb-flushing from the s390 tree to get the
  no-dat base features
- merge of kvm/master to avoid conflicts with additional sthyi fixes
- wire up the no-dat enhancements in KVM
- multiple epoch facility (z14 feature)
- Configuration z/Architecture Mode
- more sthyi fixes
- gdb server range checking fix
- small code cleanups
  • Loading branch information
rkrcmar committed Sep 7, 2017
2 parents 712b12d + c95c895 commit 6e0ff1b
Show file tree
Hide file tree
Showing 25 changed files with 597 additions and 124 deletions.
14 changes: 13 additions & 1 deletion Documentation/virtual/kvm/devices/vm.txt
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@ Architectures: s390

3.1. ATTRIBUTE: KVM_S390_VM_TOD_HIGH

Allows user space to set/get the TOD clock extension (u8).
Allows user space to set/get the TOD clock extension (u8) (superseded by
KVM_S390_VM_TOD_EXT).

Parameters: address of a buffer in user space to store the data (u8) to
Returns: -EFAULT if the given address is not accessible from kernel space
Expand All @@ -190,6 +191,17 @@ the POP (u64).
Parameters: address of a buffer in user space to store the data (u64) to
Returns: -EFAULT if the given address is not accessible from kernel space

3.3. ATTRIBUTE: KVM_S390_VM_TOD_EXT
Allows user space to set/get bits 0-63 of the TOD clock register as defined in
the POP (u64). If the guest CPU model supports the TOD clock extension (u8), it
also allows user space to get/set it. If the guest CPU model does not support
it, it is stored as 0 and not allowed to be set to a value != 0.

Parameters: address of a buffer in user space to store the data
(kvm_s390_vm_tod_clock) to
Returns: -EFAULT if the given address is not accessible from kernel space
-EINVAL if setting the TOD clock extension to != 0 is not supported

4. GROUP: KVM_S390_VM_CRYPTO
Architectures: s390

Expand Down
6 changes: 5 additions & 1 deletion arch/s390/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,9 @@ struct kvm_s390_sie_block {
#define ECB3_RI 0x01
__u8 ecb3; /* 0x0063 */
__u32 scaol; /* 0x0064 */
__u8 reserved68[4]; /* 0x0068 */
__u8 reserved68; /* 0x0068 */
__u8 epdx; /* 0x0069 */
__u8 reserved6a[2]; /* 0x006a */
__u32 todpr; /* 0x006c */
__u8 reserved70[16]; /* 0x0070 */
__u64 mso; /* 0x0080 */
Expand Down Expand Up @@ -265,6 +267,7 @@ struct kvm_s390_sie_block {
__u64 cbrlo; /* 0x01b8 */
__u8 reserved1c0[8]; /* 0x01c0 */
#define ECD_HOSTREGMGMT 0x20000000
#define ECD_MEF 0x08000000
__u32 ecd; /* 0x01c8 */
__u8 reserved1cc[18]; /* 0x01cc */
__u64 pp; /* 0x01de */
Expand Down Expand Up @@ -739,6 +742,7 @@ struct kvm_arch{
struct kvm_s390_cpu_model model;
struct kvm_s390_crypto crypto;
struct kvm_s390_vsie vsie;
u8 epdx;
u64 epoch;
struct kvm_s390_migration_state *migration_state;
/* subset of available cpu features enabled by user space */
Expand Down
3 changes: 2 additions & 1 deletion arch/s390/include/asm/page-states.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
#define ESSA_SET_POT_VOLATILE 4
#define ESSA_SET_STABLE_RESIDENT 5
#define ESSA_SET_STABLE_IF_RESIDENT 6
#define ESSA_SET_STABLE_NODAT 7

#define ESSA_MAX ESSA_SET_STABLE_IF_RESIDENT
#define ESSA_MAX ESSA_SET_STABLE_NODAT

#endif
3 changes: 3 additions & 0 deletions arch/s390/include/asm/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ static inline int page_reset_referenced(unsigned long addr)
struct page;
void arch_free_page(struct page *page, int order);
void arch_alloc_page(struct page *page, int order);
void arch_set_page_dat(struct page *page, int order);
void arch_set_page_nodat(struct page *page, int order);
int arch_test_page_nodat(struct page *page);
void arch_set_page_states(int make_stable);

static inline int devmem_is_allowed(unsigned long pfn)
Expand Down
88 changes: 67 additions & 21 deletions arch/s390/include/asm/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ static inline int is_module_addr(void *addr)

/* Guest Page State used for virtualization */
#define _PGSTE_GPS_ZERO 0x0000000080000000UL
#define _PGSTE_GPS_NODAT 0x0000000040000000UL
#define _PGSTE_GPS_USAGE_MASK 0x0000000003000000UL
#define _PGSTE_GPS_USAGE_STABLE 0x0000000000000000UL
#define _PGSTE_GPS_USAGE_UNUSED 0x0000000001000000UL
Expand Down Expand Up @@ -952,15 +953,30 @@ static inline pte_t pte_mkhuge(pte_t pte)
#define IPTE_GLOBAL 0
#define IPTE_LOCAL 1

static inline void __ptep_ipte(unsigned long address, pte_t *ptep, int local)
#define IPTE_NODAT 0x400
#define IPTE_GUEST_ASCE 0x800

static inline void __ptep_ipte(unsigned long address, pte_t *ptep,
unsigned long opt, unsigned long asce,
int local)
{
unsigned long pto = (unsigned long) ptep;

/* Invalidation + TLB flush for the pte */
if (__builtin_constant_p(opt) && opt == 0) {
/* Invalidation + TLB flush for the pte */
asm volatile(
" .insn rrf,0xb2210000,%[r1],%[r2],0,%[m4]"
: "+m" (*ptep) : [r1] "a" (pto), [r2] "a" (address),
[m4] "i" (local));
return;
}

/* Invalidate ptes with options + TLB flush of the ptes */
opt = opt | (asce & _ASCE_ORIGIN);
asm volatile(
" .insn rrf,0xb2210000,%[r1],%[r2],0,%[m4]"
: "+m" (*ptep) : [r1] "a" (pto), [r2] "a" (address),
[m4] "i" (local));
" .insn rrf,0xb2210000,%[r1],%[r2],%[r3],%[m4]"
: [r2] "+a" (address), [r3] "+a" (opt)
: [r1] "a" (pto), [m4] "i" (local) : "memory");
}

static inline void __ptep_ipte_range(unsigned long address, int nr,
Expand Down Expand Up @@ -1341,31 +1357,61 @@ static inline void __pmdp_csp(pmd_t *pmdp)
#define IDTE_GLOBAL 0
#define IDTE_LOCAL 1

static inline void __pmdp_idte(unsigned long address, pmd_t *pmdp, int local)
#define IDTE_PTOA 0x0800
#define IDTE_NODAT 0x1000
#define IDTE_GUEST_ASCE 0x2000

static inline void __pmdp_idte(unsigned long addr, pmd_t *pmdp,
unsigned long opt, unsigned long asce,
int local)
{
unsigned long sto;

sto = (unsigned long) pmdp - pmd_index(address) * sizeof(pmd_t);
asm volatile(
" .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]"
: "+m" (*pmdp)
: [r1] "a" (sto), [r2] "a" ((address & HPAGE_MASK)),
[m4] "i" (local)
: "cc" );
sto = (unsigned long) pmdp - pmd_index(addr) * sizeof(pmd_t);
if (__builtin_constant_p(opt) && opt == 0) {
/* flush without guest asce */
asm volatile(
" .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]"
: "+m" (*pmdp)
: [r1] "a" (sto), [r2] "a" ((addr & HPAGE_MASK)),
[m4] "i" (local)
: "cc" );
} else {
/* flush with guest asce */
asm volatile(
" .insn rrf,0xb98e0000,%[r1],%[r2],%[r3],%[m4]"
: "+m" (*pmdp)
: [r1] "a" (sto), [r2] "a" ((addr & HPAGE_MASK) | opt),
[r3] "a" (asce), [m4] "i" (local)
: "cc" );
}
}

static inline void __pudp_idte(unsigned long address, pud_t *pudp, int local)
static inline void __pudp_idte(unsigned long addr, pud_t *pudp,
unsigned long opt, unsigned long asce,
int local)
{
unsigned long r3o;

r3o = (unsigned long) pudp - pud_index(address) * sizeof(pud_t);
r3o = (unsigned long) pudp - pud_index(addr) * sizeof(pud_t);
r3o |= _ASCE_TYPE_REGION3;
asm volatile(
" .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]"
: "+m" (*pudp)
: [r1] "a" (r3o), [r2] "a" ((address & PUD_MASK)),
[m4] "i" (local)
: "cc");
if (__builtin_constant_p(opt) && opt == 0) {
/* flush without guest asce */
asm volatile(
" .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]"
: "+m" (*pudp)
: [r1] "a" (r3o), [r2] "a" ((addr & PUD_MASK)),
[m4] "i" (local)
: "cc");
} else {
/* flush with guest asce */
asm volatile(
" .insn rrf,0xb98e0000,%[r1],%[r2],%[r3],%[m4]"
: "+m" (*pudp)
: [r1] "a" (r3o), [r2] "a" ((addr & PUD_MASK) | opt),
[r3] "a" (asce), [m4] "i" (local)
: "cc" );
}
}

pmd_t pmdp_xchg_direct(struct mm_struct *, unsigned long, pmd_t *, pmd_t);
Expand Down
9 changes: 6 additions & 3 deletions arch/s390/include/asm/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@
#define MACHINE_FLAG_TE _BITUL(11)
#define MACHINE_FLAG_TLB_LC _BITUL(12)
#define MACHINE_FLAG_VX _BITUL(13)
#define MACHINE_FLAG_NX _BITUL(14)
#define MACHINE_FLAG_GS _BITUL(15)
#define MACHINE_FLAG_TLB_GUEST _BITUL(14)
#define MACHINE_FLAG_NX _BITUL(15)
#define MACHINE_FLAG_GS _BITUL(16)

#define LPP_MAGIC _BITUL(31)
#define LPP_PFAULT_PID_MASK _AC(0xffffffff, UL)
Expand Down Expand Up @@ -68,6 +69,7 @@ extern void detect_memory_memblock(void);
#define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE)
#define MACHINE_HAS_TLB_LC (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_LC)
#define MACHINE_HAS_VX (S390_lowcore.machine_flags & MACHINE_FLAG_VX)
#define MACHINE_HAS_TLB_GUEST (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_GUEST)
#define MACHINE_HAS_NX (S390_lowcore.machine_flags & MACHINE_FLAG_NX)
#define MACHINE_HAS_GS (S390_lowcore.machine_flags & MACHINE_FLAG_GS)

Expand Down Expand Up @@ -106,7 +108,8 @@ extern void pfault_fini(void);

void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault);

extern void cmma_init(void);
void cmma_init(void);
void cmma_init_nodat(void);

extern void (*_machine_restart)(char *command);
extern void (*_machine_halt)(void);
Expand Down
7 changes: 6 additions & 1 deletion arch/s390/include/asm/tlbflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,15 @@ static inline void __tlb_flush_local(void)
*/
static inline void __tlb_flush_idte(unsigned long asce)
{
unsigned long opt;

opt = IDTE_PTOA;
if (MACHINE_HAS_TLB_GUEST)
opt |= IDTE_GUEST_ASCE;
/* Global TLB flush for the mm */
asm volatile(
" .insn rrf,0xb98e0000,0,%0,%1,0"
: : "a" (2048), "a" (asce) : "cc");
: : "a" (opt), "a" (asce) : "cc");
}

#ifdef CONFIG_SMP
Expand Down
6 changes: 6 additions & 0 deletions arch/s390/include/uapi/asm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ struct kvm_s390_io_adapter_req {
/* kvm attributes for KVM_S390_VM_TOD */
#define KVM_S390_VM_TOD_LOW 0
#define KVM_S390_VM_TOD_HIGH 1
#define KVM_S390_VM_TOD_EXT 2

struct kvm_s390_vm_tod_clock {
__u8 epoch_idx;
__u64 tod;
};

/* kvm attributes for KVM_S390_VM_CPU_MODEL */
/* processor related attributes are r/w */
Expand Down
24 changes: 19 additions & 5 deletions arch/s390/kernel/suspend.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,16 @@ int page_key_alloc(unsigned long pages)
*/
void page_key_read(unsigned long *pfn)
{
struct page *page;
unsigned long addr;

addr = (unsigned long) page_address(pfn_to_page(*pfn));
*(unsigned char *) pfn = (unsigned char) page_get_storage_key(addr);
unsigned char key;

page = pfn_to_page(*pfn);
addr = (unsigned long) page_address(page);
key = (unsigned char) page_get_storage_key(addr) & 0x7f;
if (arch_test_page_nodat(page))
key |= 0x80;
*(unsigned char *) pfn = key;
}

/*
Expand All @@ -126,8 +132,16 @@ void page_key_memorize(unsigned long *pfn)
*/
void page_key_write(void *address)
{
page_set_storage_key((unsigned long) address,
page_key_rp->data[page_key_rx], 0);
struct page *page;
unsigned char key;

key = page_key_rp->data[page_key_rx];
page_set_storage_key((unsigned long) address, key & 0x7f, 0);
page = virt_to_page(address);
if (key & 0x80)
arch_set_page_nodat(page, 0);
else
arch_set_page_dat(page, 0);
if (++page_key_rx >= PAGE_KEY_DATA_SIZE)
return;
page_key_rp = page_key_rp->next;
Expand Down
2 changes: 2 additions & 0 deletions arch/s390/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ int vdso_alloc_per_cpu(struct lowcore *lowcore)
page_frame = get_zeroed_page(GFP_KERNEL);
if (!segment_table || !page_table || !page_frame)
goto out;
arch_set_page_dat(virt_to_page(segment_table), SEGMENT_ORDER);
arch_set_page_dat(virt_to_page(page_table), 0);

/* Initialize per-cpu vdso data page */
vd = (struct vdso_per_cpu_data *) page_frame;
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kvm/guestdbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ static inline int in_addr_range(u64 addr, u64 a, u64 b)
return (addr >= a) && (addr <= b);
else
/* "overflowing" interval */
return (addr <= a) && (addr >= b);
return (addr >= a) || (addr <= b);
}

#define end_of_range(bp_info) (bp_info->addr + bp_info->len - 1)
Expand Down
6 changes: 4 additions & 2 deletions arch/s390/kvm/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2479,6 +2479,7 @@ void kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu,
struct kvm_s390_mchk_info *mchk;
union mci mci;
__u64 cr14 = 0; /* upper bits are not used */
int rc;

mci.val = mcck_info->mcic;
if (mci.sr)
Expand All @@ -2496,12 +2497,13 @@ void kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu,
if (mci.ck) {
/* Inject the floating machine check */
inti.type = KVM_S390_MCHK;
WARN_ON_ONCE(__inject_vm(vcpu->kvm, &inti));
rc = __inject_vm(vcpu->kvm, &inti);
} else {
/* Inject the machine check to specified vcpu */
irq.type = KVM_S390_MCHK;
WARN_ON_ONCE(kvm_s390_inject_vcpu(vcpu, &irq));
rc = kvm_s390_inject_vcpu(vcpu, &irq);
}
WARN_ON_ONCE(rc);
}

int kvm_set_routing_entry(struct kvm *kvm,
Expand Down
Loading

0 comments on commit 6e0ff1b

Please sign in to comment.