mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'kvm-ppc-fixes-5.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc into kvm-master
PPC KVM fix for 5.5 - Fix a bug where we try to do an ultracall on a system without an ultravisor.
This commit is contained in:
@@ -5,7 +5,7 @@ The Definitive KVM (Kernel-based Virtual Machine) API Documentation
|
||||
----------------------
|
||||
|
||||
The kvm API is a set of ioctls that are issued to control various aspects
|
||||
of a virtual machine. The ioctls belong to three classes:
|
||||
of a virtual machine. The ioctls belong to the following classes:
|
||||
|
||||
- System ioctls: These query and set global attributes which affect the
|
||||
whole kvm subsystem. In addition a system ioctl is used to create
|
||||
@@ -3002,6 +3002,9 @@ can be determined by querying the KVM_CAP_GUEST_DEBUG_HW_BPS and
|
||||
KVM_CAP_GUEST_DEBUG_HW_WPS capabilities which return a positive number
|
||||
indicating the number of supported registers.
|
||||
|
||||
For ppc, the KVM_CAP_PPC_GUEST_DEBUG_SSTEP capability indicates whether
|
||||
the single-step debug event (KVM_GUESTDBG_SINGLESTEP) is supported.
|
||||
|
||||
When debug events exit the main run loop with the reason
|
||||
KVM_EXIT_DEBUG with the kvm_debug_exit_arch part of the kvm_run
|
||||
structure containing architecture specific debug information.
|
||||
@@ -4146,6 +4149,24 @@ Valid values for 'action':
|
||||
#define KVM_PMU_EVENT_ALLOW 0
|
||||
#define KVM_PMU_EVENT_DENY 1
|
||||
|
||||
4.121 KVM_PPC_SVM_OFF
|
||||
|
||||
Capability: basic
|
||||
Architectures: powerpc
|
||||
Type: vm ioctl
|
||||
Parameters: none
|
||||
Returns: 0 on successful completion,
|
||||
Errors:
|
||||
EINVAL: if ultravisor failed to terminate the secure guest
|
||||
ENOMEM: if hypervisor failed to allocate new radix page tables for guest
|
||||
|
||||
This ioctl is used to turn off the secure mode of the guest or transition
|
||||
the guest from secure mode to normal mode. This is invoked when the guest
|
||||
is reset. This has no effect if called for a normal guest.
|
||||
|
||||
This ioctl issues an ultravisor call to terminate the secure guest,
|
||||
unpins the VPA pages and releases all the device pages that are used to
|
||||
track the secure pages by hypervisor.
|
||||
|
||||
5. The kvm_run structure
|
||||
------------------------
|
||||
|
||||
@@ -3,9 +3,19 @@ XICS interrupt controller
|
||||
Device type supported: KVM_DEV_TYPE_XICS
|
||||
|
||||
Groups:
|
||||
KVM_DEV_XICS_SOURCES
|
||||
1. KVM_DEV_XICS_GRP_SOURCES
|
||||
Attributes: One per interrupt source, indexed by the source number.
|
||||
|
||||
2. KVM_DEV_XICS_GRP_CTRL
|
||||
Attributes:
|
||||
2.1 KVM_DEV_XICS_NR_SERVERS (write only)
|
||||
The kvm_device_attr.addr points to a __u32 value which is the number of
|
||||
interrupt server numbers (ie, highest possible vcpu id plus one).
|
||||
Errors:
|
||||
-EINVAL: Value greater than KVM_MAX_VCPU_ID.
|
||||
-EFAULT: Invalid user pointer for attr->addr.
|
||||
-EBUSY: A vcpu is already connected to the device.
|
||||
|
||||
This device emulates the XICS (eXternal Interrupt Controller
|
||||
Specification) defined in PAPR. The XICS has a set of interrupt
|
||||
sources, each identified by a 20-bit source number, and a set of
|
||||
@@ -38,7 +48,7 @@ least-significant end of the word:
|
||||
|
||||
Each source has 64 bits of state that can be read and written using
|
||||
the KVM_GET_DEVICE_ATTR and KVM_SET_DEVICE_ATTR ioctls, specifying the
|
||||
KVM_DEV_XICS_SOURCES attribute group, with the attribute number being
|
||||
KVM_DEV_XICS_GRP_SOURCES attribute group, with the attribute number being
|
||||
the interrupt source number. The 64 bit state word has the following
|
||||
bitfields, starting from the least-significant end of the word:
|
||||
|
||||
|
||||
@@ -78,6 +78,14 @@ the legacy interrupt mode, referred as XICS (POWER7/8).
|
||||
migrating the VM.
|
||||
Errors: none
|
||||
|
||||
1.3 KVM_DEV_XIVE_NR_SERVERS (write only)
|
||||
The kvm_device_attr.addr points to a __u32 value which is the number of
|
||||
interrupt server numbers (ie, highest possible vcpu id plus one).
|
||||
Errors:
|
||||
-EINVAL: Value greater than KVM_MAX_VCPU_ID.
|
||||
-EFAULT: Invalid user pointer for attr->addr.
|
||||
-EBUSY: A vCPU is already connected to the device.
|
||||
|
||||
2. KVM_DEV_XIVE_GRP_SOURCE (write only)
|
||||
Initializes a new source in the XIVE device and mask it.
|
||||
Attributes:
|
||||
|
||||
@@ -451,6 +451,23 @@ config PPC_TRANSACTIONAL_MEM
|
||||
help
|
||||
Support user-mode Transactional Memory on POWERPC.
|
||||
|
||||
config PPC_UV
|
||||
bool "Ultravisor support"
|
||||
depends on KVM_BOOK3S_HV_POSSIBLE
|
||||
select ZONE_DEVICE
|
||||
select DEV_PAGEMAP_OPS
|
||||
select DEVICE_PRIVATE
|
||||
select MEMORY_HOTPLUG
|
||||
select MEMORY_HOTREMOVE
|
||||
default n
|
||||
help
|
||||
This option paravirtualizes the kernel to run in POWER platforms that
|
||||
supports the Protected Execution Facility (PEF). On such platforms,
|
||||
the ultravisor firmware runs at a privilege level above the
|
||||
hypervisor.
|
||||
|
||||
If unsure, say "N".
|
||||
|
||||
config LD_HEAD_STUB_CATCH
|
||||
bool "Reserve 256 bytes to cope with linker stubs in HEAD text" if EXPERT
|
||||
depends on PPC64
|
||||
|
||||
@@ -342,6 +342,15 @@
|
||||
#define H_TLB_INVALIDATE 0xF808
|
||||
#define H_COPY_TOFROM_GUEST 0xF80C
|
||||
|
||||
/* Flags for H_SVM_PAGE_IN */
|
||||
#define H_PAGE_IN_SHARED 0x1
|
||||
|
||||
/* Platform-specific hcalls used by the Ultravisor */
|
||||
#define H_SVM_PAGE_IN 0xEF00
|
||||
#define H_SVM_PAGE_OUT 0xEF04
|
||||
#define H_SVM_INIT_START 0xEF08
|
||||
#define H_SVM_INIT_DONE 0xEF0C
|
||||
|
||||
/* Values for 2nd argument to H_SET_MODE */
|
||||
#define H_SET_MODE_RESOURCE_SET_CIABR 1
|
||||
#define H_SET_MODE_RESOURCE_SET_DAWR 2
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_KVM_BOOK3S_UVMEM_H__
|
||||
#define __ASM_KVM_BOOK3S_UVMEM_H__
|
||||
|
||||
#ifdef CONFIG_PPC_UV
|
||||
int kvmppc_uvmem_init(void);
|
||||
void kvmppc_uvmem_free(void);
|
||||
int kvmppc_uvmem_slot_init(struct kvm *kvm, const struct kvm_memory_slot *slot);
|
||||
void kvmppc_uvmem_slot_free(struct kvm *kvm,
|
||||
const struct kvm_memory_slot *slot);
|
||||
unsigned long kvmppc_h_svm_page_in(struct kvm *kvm,
|
||||
unsigned long gra,
|
||||
unsigned long flags,
|
||||
unsigned long page_shift);
|
||||
unsigned long kvmppc_h_svm_page_out(struct kvm *kvm,
|
||||
unsigned long gra,
|
||||
unsigned long flags,
|
||||
unsigned long page_shift);
|
||||
unsigned long kvmppc_h_svm_init_start(struct kvm *kvm);
|
||||
unsigned long kvmppc_h_svm_init_done(struct kvm *kvm);
|
||||
int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn);
|
||||
void kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free,
|
||||
struct kvm *kvm);
|
||||
#else
|
||||
static inline int kvmppc_uvmem_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void kvmppc_uvmem_free(void) { }
|
||||
|
||||
static inline int
|
||||
kvmppc_uvmem_slot_init(struct kvm *kvm, const struct kvm_memory_slot *slot)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
kvmppc_uvmem_slot_free(struct kvm *kvm, const struct kvm_memory_slot *slot) { }
|
||||
|
||||
static inline unsigned long
|
||||
kvmppc_h_svm_page_in(struct kvm *kvm, unsigned long gra,
|
||||
unsigned long flags, unsigned long page_shift)
|
||||
{
|
||||
return H_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
kvmppc_h_svm_page_out(struct kvm *kvm, unsigned long gra,
|
||||
unsigned long flags, unsigned long page_shift)
|
||||
{
|
||||
return H_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static inline unsigned long kvmppc_h_svm_init_start(struct kvm *kvm)
|
||||
{
|
||||
return H_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static inline unsigned long kvmppc_h_svm_init_done(struct kvm *kvm)
|
||||
{
|
||||
return H_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static inline int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline void
|
||||
kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free,
|
||||
struct kvm *kvm) { }
|
||||
#endif /* CONFIG_PPC_UV */
|
||||
#endif /* __ASM_KVM_BOOK3S_UVMEM_H__ */
|
||||
@@ -275,6 +275,10 @@ struct kvm_hpt_info {
|
||||
|
||||
struct kvm_resize_hpt;
|
||||
|
||||
/* Flag values for kvm_arch.secure_guest */
|
||||
#define KVMPPC_SECURE_INIT_START 0x1 /* H_SVM_INIT_START has been called */
|
||||
#define KVMPPC_SECURE_INIT_DONE 0x2 /* H_SVM_INIT_DONE completed */
|
||||
|
||||
struct kvm_arch {
|
||||
unsigned int lpid;
|
||||
unsigned int smt_mode; /* # vcpus per virtual core */
|
||||
@@ -330,6 +334,8 @@ struct kvm_arch {
|
||||
#endif
|
||||
struct kvmppc_ops *kvm_ops;
|
||||
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
|
||||
struct mutex uvmem_lock;
|
||||
struct list_head uvmem_pfns;
|
||||
struct mutex mmu_setup_lock; /* nests inside vcpu mutexes */
|
||||
u64 l1_ptcr;
|
||||
int max_nested_lpid;
|
||||
@@ -401,7 +407,6 @@ struct kvmppc_mmu {
|
||||
u32 (*mfsrin)(struct kvm_vcpu *vcpu, u32 srnum);
|
||||
int (*xlate)(struct kvm_vcpu *vcpu, gva_t eaddr,
|
||||
struct kvmppc_pte *pte, bool data, bool iswrite);
|
||||
void (*reset_msr)(struct kvm_vcpu *vcpu);
|
||||
void (*tlbie)(struct kvm_vcpu *vcpu, ulong addr, bool large);
|
||||
int (*esid_to_vsid)(struct kvm_vcpu *vcpu, ulong esid, u64 *vsid);
|
||||
u64 (*ea_to_vp)(struct kvm_vcpu *vcpu, gva_t eaddr, bool data);
|
||||
|
||||
@@ -271,6 +271,7 @@ struct kvmppc_ops {
|
||||
union kvmppc_one_reg *val);
|
||||
void (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu);
|
||||
void (*vcpu_put)(struct kvm_vcpu *vcpu);
|
||||
void (*inject_interrupt)(struct kvm_vcpu *vcpu, int vec, u64 srr1_flags);
|
||||
void (*set_msr)(struct kvm_vcpu *vcpu, u64 msr);
|
||||
int (*vcpu_run)(struct kvm_run *run, struct kvm_vcpu *vcpu);
|
||||
struct kvm_vcpu *(*vcpu_create)(struct kvm *kvm, unsigned int id);
|
||||
@@ -321,6 +322,7 @@ struct kvmppc_ops {
|
||||
int size);
|
||||
int (*store_to_eaddr)(struct kvm_vcpu *vcpu, ulong *eaddr, void *ptr,
|
||||
int size);
|
||||
int (*svm_off)(struct kvm *kvm);
|
||||
};
|
||||
|
||||
extern struct kvmppc_ops *kvmppc_hv_ops;
|
||||
|
||||
@@ -748,6 +748,18 @@
|
||||
#define SPRN_USPRG7 0x107 /* SPRG7 userspace read */
|
||||
#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */
|
||||
#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
/*
|
||||
* Bits loaded from MSR upon interrupt.
|
||||
* PPC (64-bit) bits 33-36,42-47 are interrupt dependent, the others are
|
||||
* loaded from MSR. The exception is that SRESET and MCE do not always load
|
||||
* bit 62 (RI) from MSR. Don't use PPC_BITMASK for this because 32-bit uses
|
||||
* it.
|
||||
*/
|
||||
#define SRR1_MSR_BITS (~0x783f0000UL)
|
||||
#endif
|
||||
|
||||
#define SRR1_ISI_NOPT 0x40000000 /* ISI: Not found in hash */
|
||||
#define SRR1_ISI_N_OR_G 0x10000000 /* ISI: Access is no-exec or G */
|
||||
#define SRR1_ISI_PROT 0x08000000 /* ISI: Other protection fault */
|
||||
|
||||
@@ -26,8 +26,14 @@
|
||||
#define UV_WRITE_PATE 0xF104
|
||||
#define UV_RETURN 0xF11C
|
||||
#define UV_ESM 0xF110
|
||||
#define UV_REGISTER_MEM_SLOT 0xF120
|
||||
#define UV_UNREGISTER_MEM_SLOT 0xF124
|
||||
#define UV_PAGE_IN 0xF128
|
||||
#define UV_PAGE_OUT 0xF12C
|
||||
#define UV_SHARE_PAGE 0xF130
|
||||
#define UV_UNSHARE_PAGE 0xF134
|
||||
#define UV_UNSHARE_ALL_PAGES 0xF140
|
||||
#define UV_PAGE_INVAL 0xF138
|
||||
#define UV_SVM_TERMINATE 0xF13C
|
||||
|
||||
#endif /* _ASM_POWERPC_ULTRAVISOR_API_H */
|
||||
|
||||
@@ -46,4 +46,40 @@ static inline int uv_unshare_all_pages(void)
|
||||
return ucall_norets(UV_UNSHARE_ALL_PAGES);
|
||||
}
|
||||
|
||||
static inline int uv_page_in(u64 lpid, u64 src_ra, u64 dst_gpa, u64 flags,
|
||||
u64 page_shift)
|
||||
{
|
||||
return ucall_norets(UV_PAGE_IN, lpid, src_ra, dst_gpa, flags,
|
||||
page_shift);
|
||||
}
|
||||
|
||||
static inline int uv_page_out(u64 lpid, u64 dst_ra, u64 src_gpa, u64 flags,
|
||||
u64 page_shift)
|
||||
{
|
||||
return ucall_norets(UV_PAGE_OUT, lpid, dst_ra, src_gpa, flags,
|
||||
page_shift);
|
||||
}
|
||||
|
||||
static inline int uv_register_mem_slot(u64 lpid, u64 start_gpa, u64 size,
|
||||
u64 flags, u64 slotid)
|
||||
{
|
||||
return ucall_norets(UV_REGISTER_MEM_SLOT, lpid, start_gpa,
|
||||
size, flags, slotid);
|
||||
}
|
||||
|
||||
static inline int uv_unregister_mem_slot(u64 lpid, u64 slotid)
|
||||
{
|
||||
return ucall_norets(UV_UNREGISTER_MEM_SLOT, lpid, slotid);
|
||||
}
|
||||
|
||||
static inline int uv_page_inval(u64 lpid, u64 gpa, u64 page_shift)
|
||||
{
|
||||
return ucall_norets(UV_PAGE_INVAL, lpid, gpa, page_shift);
|
||||
}
|
||||
|
||||
static inline int uv_svm_terminate(u64 lpid)
|
||||
{
|
||||
return ucall_norets(UV_SVM_TERMINATE, lpid);
|
||||
}
|
||||
|
||||
#endif /* _ASM_POWERPC_ULTRAVISOR_H */
|
||||
|
||||
@@ -667,6 +667,8 @@ struct kvm_ppc_cpu_char {
|
||||
|
||||
/* PPC64 eXternal Interrupt Controller Specification */
|
||||
#define KVM_DEV_XICS_GRP_SOURCES 1 /* 64-bit source attributes */
|
||||
#define KVM_DEV_XICS_GRP_CTRL 2
|
||||
#define KVM_DEV_XICS_NR_SERVERS 1
|
||||
|
||||
/* Layout of 64-bit source attribute values */
|
||||
#define KVM_XICS_DESTINATION_SHIFT 0
|
||||
@@ -683,6 +685,7 @@ struct kvm_ppc_cpu_char {
|
||||
#define KVM_DEV_XIVE_GRP_CTRL 1
|
||||
#define KVM_DEV_XIVE_RESET 1
|
||||
#define KVM_DEV_XIVE_EQ_SYNC 2
|
||||
#define KVM_DEV_XIVE_NR_SERVERS 3
|
||||
#define KVM_DEV_XIVE_GRP_SOURCE 2 /* 64-bit source identifier */
|
||||
#define KVM_DEV_XIVE_GRP_SOURCE_CONFIG 3 /* 64-bit source identifier */
|
||||
#define KVM_DEV_XIVE_GRP_EQ_CONFIG 4 /* 64-bit EQ identifier */
|
||||
|
||||
@@ -71,6 +71,9 @@ kvm-hv-y += \
|
||||
book3s_64_mmu_radix.o \
|
||||
book3s_hv_nested.o
|
||||
|
||||
kvm-hv-$(CONFIG_PPC_UV) += \
|
||||
book3s_hv_uvmem.o
|
||||
|
||||
kvm-hv-$(CONFIG_PPC_TRANSACTIONAL_MEM) += \
|
||||
book3s_hv_tm.o
|
||||
|
||||
|
||||
@@ -74,27 +74,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
void kvmppc_unfixup_split_real(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) {
|
||||
ulong pc = kvmppc_get_pc(vcpu);
|
||||
ulong lr = kvmppc_get_lr(vcpu);
|
||||
if ((pc & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS)
|
||||
kvmppc_set_pc(vcpu, pc & ~SPLIT_HACK_MASK);
|
||||
if ((lr & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS)
|
||||
kvmppc_set_lr(vcpu, lr & ~SPLIT_HACK_MASK);
|
||||
vcpu->arch.hflags &= ~BOOK3S_HFLAG_SPLIT_HACK;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvmppc_unfixup_split_real);
|
||||
|
||||
static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (!is_kvmppc_hv_enabled(vcpu->kvm))
|
||||
return to_book3s(vcpu)->hior;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
|
||||
unsigned long pending_now, unsigned long old_pending)
|
||||
{
|
||||
@@ -134,11 +113,7 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
|
||||
|
||||
void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
|
||||
{
|
||||
kvmppc_unfixup_split_real(vcpu);
|
||||
kvmppc_set_srr0(vcpu, kvmppc_get_pc(vcpu));
|
||||
kvmppc_set_srr1(vcpu, (kvmppc_get_msr(vcpu) & ~0x783f0000ul) | flags);
|
||||
kvmppc_set_pc(vcpu, kvmppc_interrupt_offset(vcpu) + vec);
|
||||
vcpu->arch.mmu.reset_msr(vcpu);
|
||||
vcpu->kvm->arch.kvm_ops->inject_interrupt(vcpu, vec, flags);
|
||||
}
|
||||
|
||||
static int kvmppc_book3s_vec2irqprio(unsigned int vec)
|
||||
|
||||
@@ -32,4 +32,7 @@ extern void kvmppc_emulate_tabort(struct kvm_vcpu *vcpu, int ra_val);
|
||||
static inline void kvmppc_emulate_tabort(struct kvm_vcpu *vcpu, int ra_val) {}
|
||||
#endif
|
||||
|
||||
extern void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr);
|
||||
extern void kvmppc_inject_interrupt_hv(struct kvm_vcpu *vcpu, int vec, u64 srr1_flags);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -90,11 +90,6 @@ static u64 kvmppc_mmu_book3s_32_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr,
|
||||
return (((u64)eaddr >> 12) & 0xffff) | (vsid << 16);
|
||||
}
|
||||
|
||||
static void kvmppc_mmu_book3s_32_reset_msr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
kvmppc_set_msr(vcpu, 0);
|
||||
}
|
||||
|
||||
static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvm_vcpu *vcpu,
|
||||
u32 sre, gva_t eaddr,
|
||||
bool primary)
|
||||
@@ -406,7 +401,6 @@ void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu)
|
||||
mmu->mtsrin = kvmppc_mmu_book3s_32_mtsrin;
|
||||
mmu->mfsrin = kvmppc_mmu_book3s_32_mfsrin;
|
||||
mmu->xlate = kvmppc_mmu_book3s_32_xlate;
|
||||
mmu->reset_msr = kvmppc_mmu_book3s_32_reset_msr;
|
||||
mmu->tlbie = kvmppc_mmu_book3s_32_tlbie;
|
||||
mmu->esid_to_vsid = kvmppc_mmu_book3s_32_esid_to_vsid;
|
||||
mmu->ea_to_vp = kvmppc_mmu_book3s_32_ea_to_vp;
|
||||
|
||||
@@ -24,20 +24,6 @@
|
||||
#define dprintk(X...) do { } while(0)
|
||||
#endif
|
||||
|
||||
static void kvmppc_mmu_book3s_64_reset_msr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
unsigned long msr = vcpu->arch.intr_msr;
|
||||
unsigned long cur_msr = kvmppc_get_msr(vcpu);
|
||||
|
||||
/* If transactional, change to suspend mode on IRQ delivery */
|
||||
if (MSR_TM_TRANSACTIONAL(cur_msr))
|
||||
msr |= MSR_TS_S;
|
||||
else
|
||||
msr |= cur_msr & MSR_TS_MASK;
|
||||
|
||||
kvmppc_set_msr(vcpu, msr);
|
||||
}
|
||||
|
||||
static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe(
|
||||
struct kvm_vcpu *vcpu,
|
||||
gva_t eaddr)
|
||||
@@ -676,7 +662,6 @@ void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu)
|
||||
mmu->slbie = kvmppc_mmu_book3s_64_slbie;
|
||||
mmu->slbia = kvmppc_mmu_book3s_64_slbia;
|
||||
mmu->xlate = kvmppc_mmu_book3s_64_xlate;
|
||||
mmu->reset_msr = kvmppc_mmu_book3s_64_reset_msr;
|
||||
mmu->tlbie = kvmppc_mmu_book3s_64_tlbie;
|
||||
mmu->esid_to_vsid = kvmppc_mmu_book3s_64_esid_to_vsid;
|
||||
mmu->ea_to_vp = kvmppc_mmu_book3s_64_ea_to_vp;
|
||||
|
||||
@@ -275,18 +275,6 @@ int kvmppc_mmu_hv_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kvmppc_mmu_book3s_64_hv_reset_msr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
unsigned long msr = vcpu->arch.intr_msr;
|
||||
|
||||
/* If transactional, change to suspend mode on IRQ delivery */
|
||||
if (MSR_TM_TRANSACTIONAL(vcpu->arch.shregs.msr))
|
||||
msr |= MSR_TS_S;
|
||||
else
|
||||
msr |= vcpu->arch.shregs.msr & MSR_TS_MASK;
|
||||
kvmppc_set_msr(vcpu, msr);
|
||||
}
|
||||
|
||||
static long kvmppc_virtmode_do_h_enter(struct kvm *kvm, unsigned long flags,
|
||||
long pte_index, unsigned long pteh,
|
||||
unsigned long ptel, unsigned long *pte_idx_ret)
|
||||
@@ -508,6 +496,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
struct vm_area_struct *vma;
|
||||
unsigned long rcbits;
|
||||
long mmio_update;
|
||||
struct mm_struct *mm;
|
||||
|
||||
if (kvm_is_radix(kvm))
|
||||
return kvmppc_book3s_radix_page_fault(run, vcpu, ea, dsisr);
|
||||
@@ -584,6 +573,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
is_ci = false;
|
||||
pfn = 0;
|
||||
page = NULL;
|
||||
mm = current->mm;
|
||||
pte_size = PAGE_SIZE;
|
||||
writing = (dsisr & DSISR_ISSTORE) != 0;
|
||||
/* If writing != 0, then the HPTE must allow writing, if we get here */
|
||||
@@ -592,8 +582,8 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
npages = get_user_pages_fast(hva, 1, writing ? FOLL_WRITE : 0, pages);
|
||||
if (npages < 1) {
|
||||
/* Check if it's an I/O mapping */
|
||||
down_read(¤t->mm->mmap_sem);
|
||||
vma = find_vma(current->mm, hva);
|
||||
down_read(&mm->mmap_sem);
|
||||
vma = find_vma(mm, hva);
|
||||
if (vma && vma->vm_start <= hva && hva + psize <= vma->vm_end &&
|
||||
(vma->vm_flags & VM_PFNMAP)) {
|
||||
pfn = vma->vm_pgoff +
|
||||
@@ -602,7 +592,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
is_ci = pte_ci(__pte((pgprot_val(vma->vm_page_prot))));
|
||||
write_ok = vma->vm_flags & VM_WRITE;
|
||||
}
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
up_read(&mm->mmap_sem);
|
||||
if (!pfn)
|
||||
goto out_put;
|
||||
} else {
|
||||
@@ -621,8 +611,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
* hugepage split and collapse.
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
ptep = find_current_mm_pte(current->mm->pgd,
|
||||
hva, NULL, NULL);
|
||||
ptep = find_current_mm_pte(mm->pgd, hva, NULL, NULL);
|
||||
if (ptep) {
|
||||
pte = kvmppc_read_update_linux_pte(ptep, 1);
|
||||
if (__pte_write(pte))
|
||||
@@ -2000,7 +1989,7 @@ int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *ghf)
|
||||
ret = anon_inode_getfd("kvm-htab", &kvm_htab_fops, ctx, rwflag | O_CLOEXEC);
|
||||
if (ret < 0) {
|
||||
kfree(ctx);
|
||||
kvm_put_kvm(kvm);
|
||||
kvm_put_kvm_no_destroy(kvm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2161,7 +2150,6 @@ void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu)
|
||||
vcpu->arch.slb_nr = 32; /* POWER7/POWER8 */
|
||||
|
||||
mmu->xlate = kvmppc_mmu_book3s_64_hv_xlate;
|
||||
mmu->reset_msr = kvmppc_mmu_book3s_64_hv_reset_msr;
|
||||
|
||||
vcpu->arch.hflags |= BOOK3S_HFLAG_SLB;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/pte-walk.h>
|
||||
#include <asm/ultravisor.h>
|
||||
#include <asm/kvm_book3s_uvmem.h>
|
||||
|
||||
/*
|
||||
* Supported radix tree geometry.
|
||||
@@ -915,6 +917,9 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
if (!(dsisr & DSISR_PRTABLE_FAULT))
|
||||
gpa |= ea & 0xfff;
|
||||
|
||||
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE)
|
||||
return kvmppc_send_page_to_uv(kvm, gfn);
|
||||
|
||||
/* Get the corresponding memslot */
|
||||
memslot = gfn_to_memslot(kvm, gfn);
|
||||
|
||||
@@ -972,6 +977,11 @@ int kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
||||
unsigned long gpa = gfn << PAGE_SHIFT;
|
||||
unsigned int shift;
|
||||
|
||||
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE) {
|
||||
uv_page_inval(kvm->arch.lpid, gpa, PAGE_SHIFT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift);
|
||||
if (ptep && pte_present(*ptep))
|
||||
kvmppc_unmap_pte(kvm, ptep, gpa, shift, memslot,
|
||||
@@ -989,6 +999,9 @@ int kvm_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
||||
int ref = 0;
|
||||
unsigned long old, *rmapp;
|
||||
|
||||
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE)
|
||||
return ref;
|
||||
|
||||
ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift);
|
||||
if (ptep && pte_present(*ptep) && pte_young(*ptep)) {
|
||||
old = kvmppc_radix_update_pte(kvm, ptep, _PAGE_ACCESSED, 0,
|
||||
@@ -1013,6 +1026,9 @@ int kvm_test_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
||||
unsigned int shift;
|
||||
int ref = 0;
|
||||
|
||||
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE)
|
||||
return ref;
|
||||
|
||||
ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift);
|
||||
if (ptep && pte_present(*ptep) && pte_young(*ptep))
|
||||
ref = 1;
|
||||
@@ -1030,6 +1046,9 @@ static int kvm_radix_test_clear_dirty(struct kvm *kvm,
|
||||
int ret = 0;
|
||||
unsigned long old, *rmapp;
|
||||
|
||||
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE)
|
||||
return ret;
|
||||
|
||||
ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift);
|
||||
if (ptep && pte_present(*ptep) && pte_dirty(*ptep)) {
|
||||
ret = 1;
|
||||
@@ -1082,6 +1101,12 @@ void kvmppc_radix_flush_memslot(struct kvm *kvm,
|
||||
unsigned long gpa;
|
||||
unsigned int shift;
|
||||
|
||||
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_START)
|
||||
kvmppc_uvmem_drop_pages(memslot, kvm);
|
||||
|
||||
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE)
|
||||
return;
|
||||
|
||||
gpa = memslot->base_gfn << PAGE_SHIFT;
|
||||
spin_lock(&kvm->mmu_lock);
|
||||
for (n = memslot->npages; n; --n) {
|
||||
|
||||
@@ -317,7 +317,7 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
|
||||
if (ret >= 0)
|
||||
list_add_rcu(&stt->list, &kvm->arch.spapr_tce_tables);
|
||||
else
|
||||
kvm_put_kvm(kvm);
|
||||
kvm_put_kvm_no_destroy(kvm);
|
||||
|
||||
mutex_unlock(&kvm->lock);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user