You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'kvm-3.9-1' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM updates from Marcelo Tosatti: "KVM updates for the 3.9 merge window, including x86 real mode emulation fixes, stronger memory slot interface restrictions, mmu_lock spinlock hold time reduction, improved handling of large page faults on shadow, initial APICv HW acceleration support, s390 channel IO based virtio, amongst others" * tag 'kvm-3.9-1' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (143 commits) Revert "KVM: MMU: lazily drop large spte" x86: pvclock kvm: align allocation size to page size KVM: nVMX: Remove redundant get_vmcs12 from nested_vmx_exit_handled_msr x86 emulator: fix parity calculation for AAD instruction KVM: PPC: BookE: Handle alignment interrupts booke: Added DBCR4 SPR number KVM: PPC: booke: Allow multiple exception types KVM: PPC: booke: use vcpu reference from thread_struct KVM: Remove user_alloc from struct kvm_memory_slot KVM: VMX: disable apicv by default KVM: s390: Fix handling of iscs. KVM: MMU: cleanup __direct_map KVM: MMU: remove pt_access in mmu_set_spte KVM: MMU: cleanup mapping-level KVM: MMU: lazily drop large spte KVM: VMX: cleanup vmx_set_cr0(). KVM: VMX: add missing exit names to VMX_EXIT_REASONS array KVM: VMX: disable SMEP feature when guest is in non-paging mode KVM: Remove duplicate text in api.txt Revert "KVM: MMU: split kvm_mmu_free_page" ...
This commit is contained in:
@@ -219,19 +219,6 @@ allocation of vcpu ids. For example, if userspace wants
|
||||
single-threaded guest vcpus, it should make all vcpu ids be a multiple
|
||||
of the number of vcpus per vcore.
|
||||
|
||||
On powerpc using book3s_hv mode, the vcpus are mapped onto virtual
|
||||
threads in one or more virtual CPU cores. (This is because the
|
||||
hardware requires all the hardware threads in a CPU core to be in the
|
||||
same partition.) The KVM_CAP_PPC_SMT capability indicates the number
|
||||
of vcpus per virtual core (vcore). The vcore id is obtained by
|
||||
dividing the vcpu id by the number of vcpus per vcore. The vcpus in a
|
||||
given vcore will always be in the same physical core as each other
|
||||
(though that might be a different physical core from time to time).
|
||||
Userspace can control the threading (SMT) mode of the guest by its
|
||||
allocation of vcpu ids. For example, if userspace wants
|
||||
single-threaded guest vcpus, it should make all vcpu ids be a multiple
|
||||
of the number of vcpus per vcore.
|
||||
|
||||
For virtual cpus that have been created with S390 user controlled virtual
|
||||
machines, the resulting vcpu fd can be memory mapped at page offset
|
||||
KVM_S390_SIE_PAGE_OFFSET in order to obtain a memory map of the virtual
|
||||
@@ -345,7 +332,7 @@ struct kvm_sregs {
|
||||
__u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
|
||||
};
|
||||
|
||||
/* ppc -- see arch/powerpc/include/asm/kvm.h */
|
||||
/* ppc -- see arch/powerpc/include/uapi/asm/kvm.h */
|
||||
|
||||
interrupt_bitmap is a bitmap of pending external interrupts. At most
|
||||
one bit may be set. This interrupt has been acknowledged by the APIC
|
||||
@@ -892,12 +879,12 @@ It is recommended that the lower 21 bits of guest_phys_addr and userspace_addr
|
||||
be identical. This allows large pages in the guest to be backed by large
|
||||
pages in the host.
|
||||
|
||||
The flags field supports two flag, KVM_MEM_LOG_DIRTY_PAGES, which instructs
|
||||
kvm to keep track of writes to memory within the slot. See KVM_GET_DIRTY_LOG
|
||||
ioctl. The KVM_CAP_READONLY_MEM capability indicates the availability of the
|
||||
KVM_MEM_READONLY flag. When this flag is set for a memory region, KVM only
|
||||
allows read accesses. Writes will be posted to userspace as KVM_EXIT_MMIO
|
||||
exits.
|
||||
The flags field supports two flags: KVM_MEM_LOG_DIRTY_PAGES and
|
||||
KVM_MEM_READONLY. The former can be set to instruct KVM to keep track of
|
||||
writes to memory within the slot. See KVM_GET_DIRTY_LOG ioctl to know how to
|
||||
use it. The latter can be set, if KVM_CAP_READONLY_MEM capability allows it,
|
||||
to make a new slot read-only. In this case, writes to this memory will be
|
||||
posted to userspace as KVM_EXIT_MMIO exits.
|
||||
|
||||
When the KVM_CAP_SYNC_MMU capability is available, changes in the backing of
|
||||
the memory region are automatically reflected into the guest. For example, an
|
||||
@@ -931,7 +918,7 @@ documentation when it pops into existence).
|
||||
4.37 KVM_ENABLE_CAP
|
||||
|
||||
Capability: KVM_CAP_ENABLE_CAP
|
||||
Architectures: ppc
|
||||
Architectures: ppc, s390
|
||||
Type: vcpu ioctl
|
||||
Parameters: struct kvm_enable_cap (in)
|
||||
Returns: 0 on success; -1 on error
|
||||
@@ -1792,6 +1779,7 @@ registers, find a list below:
|
||||
PPC | KVM_REG_PPC_VPA_SLB | 128
|
||||
PPC | KVM_REG_PPC_VPA_DTL | 128
|
||||
PPC | KVM_REG_PPC_EPCR | 32
|
||||
PPC | KVM_REG_PPC_EPR | 32
|
||||
|
||||
ARM registers are mapped using the lower 32 bits. The upper 16 of that
|
||||
is the register group type, or coprocessor number:
|
||||
@@ -2108,6 +2096,14 @@ KVM_S390_INT_VIRTIO (vm) - virtio external interrupt; external interrupt
|
||||
KVM_S390_INT_SERVICE (vm) - sclp external interrupt; sclp parameter in parm
|
||||
KVM_S390_INT_EMERGENCY (vcpu) - sigp emergency; source cpu in parm
|
||||
KVM_S390_INT_EXTERNAL_CALL (vcpu) - sigp external call; source cpu in parm
|
||||
KVM_S390_INT_IO(ai,cssid,ssid,schid) (vm) - compound value to indicate an
|
||||
I/O interrupt (ai - adapter interrupt; cssid,ssid,schid - subchannel);
|
||||
I/O interruption parameters in parm (subchannel) and parm64 (intparm,
|
||||
interruption subclass)
|
||||
KVM_S390_MCHK (vm, vcpu) - machine check interrupt; cr 14 bits in parm,
|
||||
machine check interrupt code in parm64 (note that
|
||||
machine checks needing further payload are not
|
||||
supported by this ioctl)
|
||||
|
||||
Note that the vcpu ioctl is asynchronous to vcpu execution.
|
||||
|
||||
@@ -2359,8 +2355,8 @@ executed a memory-mapped I/O instruction which could not be satisfied
|
||||
by kvm. The 'data' member contains the written data if 'is_write' is
|
||||
true, and should be filled by application code otherwise.
|
||||
|
||||
NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_DCR
|
||||
and KVM_EXIT_PAPR the corresponding
|
||||
NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_DCR,
|
||||
KVM_EXIT_PAPR and KVM_EXIT_EPR the corresponding
|
||||
operations are complete (and guest state is consistent) only after userspace
|
||||
has re-entered the kernel with KVM_RUN. The kernel side will first finish
|
||||
incomplete operations and then check for pending signals. Userspace
|
||||
@@ -2463,6 +2459,41 @@ The possible hypercalls are defined in the Power Architecture Platform
|
||||
Requirements (PAPR) document available from www.power.org (free
|
||||
developer registration required to access it).
|
||||
|
||||
/* KVM_EXIT_S390_TSCH */
|
||||
struct {
|
||||
__u16 subchannel_id;
|
||||
__u16 subchannel_nr;
|
||||
__u32 io_int_parm;
|
||||
__u32 io_int_word;
|
||||
__u32 ipb;
|
||||
__u8 dequeued;
|
||||
} s390_tsch;
|
||||
|
||||
s390 specific. This exit occurs when KVM_CAP_S390_CSS_SUPPORT has been enabled
|
||||
and TEST SUBCHANNEL was intercepted. If dequeued is set, a pending I/O
|
||||
interrupt for the target subchannel has been dequeued and subchannel_id,
|
||||
subchannel_nr, io_int_parm and io_int_word contain the parameters for that
|
||||
interrupt. ipb is needed for instruction parameter decoding.
|
||||
|
||||
/* KVM_EXIT_EPR */
|
||||
struct {
|
||||
__u32 epr;
|
||||
} epr;
|
||||
|
||||
On FSL BookE PowerPC chips, the interrupt controller has a fast patch
|
||||
interrupt acknowledge path to the core. When the core successfully
|
||||
delivers an interrupt, it automatically populates the EPR register with
|
||||
the interrupt vector number and acknowledges the interrupt inside
|
||||
the interrupt controller.
|
||||
|
||||
In case the interrupt controller lives in user space, we need to do
|
||||
the interrupt acknowledge cycle through it to fetch the next to be
|
||||
delivered interrupt vector using this exit.
|
||||
|
||||
It gets triggered whenever both KVM_CAP_PPC_EPR are enabled and an
|
||||
external interrupt has just been delivered into the guest. User space
|
||||
should put the acknowledged interrupt vector into the 'epr' field.
|
||||
|
||||
/* Fix the size of the union. */
|
||||
char padding[256];
|
||||
};
|
||||
@@ -2584,3 +2615,34 @@ For mmu types KVM_MMU_FSL_BOOKE_NOHV and KVM_MMU_FSL_BOOKE_HV:
|
||||
where "num_sets" is the tlb_sizes[] value divided by the tlb_ways[] value.
|
||||
- The tsize field of mas1 shall be set to 4K on TLB0, even though the
|
||||
hardware ignores this value for TLB0.
|
||||
|
||||
6.4 KVM_CAP_S390_CSS_SUPPORT
|
||||
|
||||
Architectures: s390
|
||||
Parameters: none
|
||||
Returns: 0 on success; -1 on error
|
||||
|
||||
This capability enables support for handling of channel I/O instructions.
|
||||
|
||||
TEST PENDING INTERRUPTION and the interrupt portion of TEST SUBCHANNEL are
|
||||
handled in-kernel, while the other I/O instructions are passed to userspace.
|
||||
|
||||
When this capability is enabled, KVM_EXIT_S390_TSCH will occur on TEST
|
||||
SUBCHANNEL intercepts.
|
||||
|
||||
6.5 KVM_CAP_PPC_EPR
|
||||
|
||||
Architectures: ppc
|
||||
Parameters: args[0] defines whether the proxy facility is active
|
||||
Returns: 0 on success; -1 on error
|
||||
|
||||
This capability enables or disables the delivery of interrupts through the
|
||||
external proxy facility.
|
||||
|
||||
When enabled (args[0] != 0), every time the guest gets an external interrupt
|
||||
delivered, it automatically exits into user space with a KVM_EXIT_EPR exit
|
||||
to receive the topmost interrupt vector.
|
||||
|
||||
When disabled (args[0] == 0), behavior is as if this facility is unsupported.
|
||||
|
||||
When this capability is enabled, KVM_EXIT_EPR can occur.
|
||||
|
||||
@@ -187,13 +187,6 @@ Shadow pages contain the following information:
|
||||
perform a reverse map from a pte to a gfn. When role.direct is set, any
|
||||
element of this array can be calculated from the gfn field when used, in
|
||||
this case, the array of gfns is not allocated. See role.direct and gfn.
|
||||
slot_bitmap:
|
||||
A bitmap containing one bit per memory slot. If the page contains a pte
|
||||
mapping a page from memory slot n, then bit n of slot_bitmap will be set
|
||||
(if a page is aliased among several slots, then it is not guaranteed that
|
||||
all slots will be marked).
|
||||
Used during dirty logging to avoid scanning a shadow page if none if its
|
||||
pages need tracking.
|
||||
root_count:
|
||||
A counter keeping track of how many hardware registers (guest cr3 or
|
||||
pdptrs) are now pointing at the page. While this counter is nonzero, the
|
||||
|
||||
@@ -23,9 +23,7 @@
|
||||
#ifndef __ASM_KVM_HOST_H
|
||||
#define __ASM_KVM_HOST_H
|
||||
|
||||
#define KVM_MEMORY_SLOTS 32
|
||||
/* memory slots that does not exposed to userspace */
|
||||
#define KVM_PRIVATE_MEM_SLOTS 4
|
||||
#define KVM_USER_MEM_SLOTS 32
|
||||
|
||||
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
|
||||
|
||||
|
||||
@@ -955,7 +955,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
|
||||
kvm_mem.guest_phys_addr;
|
||||
kvm_userspace_mem.memory_size = kvm_mem.memory_size;
|
||||
r = kvm_vm_ioctl_set_memory_region(kvm,
|
||||
&kvm_userspace_mem, 0);
|
||||
&kvm_userspace_mem, false);
|
||||
if (r)
|
||||
goto out;
|
||||
break;
|
||||
@@ -1580,7 +1580,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
|
||||
struct kvm_memory_slot *memslot,
|
||||
struct kvm_memory_slot old,
|
||||
struct kvm_userspace_memory_region *mem,
|
||||
int user_alloc)
|
||||
bool user_alloc)
|
||||
{
|
||||
unsigned long i;
|
||||
unsigned long pfn;
|
||||
@@ -1611,7 +1611,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
|
||||
void kvm_arch_commit_memory_region(struct kvm *kvm,
|
||||
struct kvm_userspace_memory_region *mem,
|
||||
struct kvm_memory_slot old,
|
||||
int user_alloc)
|
||||
bool user_alloc)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1834,7 +1834,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
|
||||
mutex_lock(&kvm->slots_lock);
|
||||
|
||||
r = -EINVAL;
|
||||
if (log->slot >= KVM_MEMORY_SLOTS)
|
||||
if (log->slot >= KVM_USER_MEM_SLOTS)
|
||||
goto out;
|
||||
|
||||
memslot = id_to_memslot(kvm->memslots, log->slot);
|
||||
|
||||
@@ -27,4 +27,10 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq);
|
||||
#define kvm_apic_present(x) (true)
|
||||
#define kvm_lapic_enabled(x) (true)
|
||||
|
||||
static inline bool kvm_apic_vid_enabled(void)
|
||||
{
|
||||
/* IA64 has no apicv supporting, do nothing here */
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,10 +37,8 @@
|
||||
|
||||
#define KVM_MAX_VCPUS NR_CPUS
|
||||
#define KVM_MAX_VCORES NR_CPUS
|
||||
#define KVM_MEMORY_SLOTS 32
|
||||
/* memory slots that does not exposed to userspace */
|
||||
#define KVM_PRIVATE_MEM_SLOTS 4
|
||||
#define KVM_MEM_SLOTS_NUM (KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS)
|
||||
#define KVM_USER_MEM_SLOTS 32
|
||||
#define KVM_MEM_SLOTS_NUM KVM_USER_MEM_SLOTS
|
||||
|
||||
#ifdef CONFIG_KVM_MMIO
|
||||
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
|
||||
@@ -523,6 +521,8 @@ struct kvm_vcpu_arch {
|
||||
u8 sane;
|
||||
u8 cpu_type;
|
||||
u8 hcall_needed;
|
||||
u8 epr_enabled;
|
||||
u8 epr_needed;
|
||||
|
||||
u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
|
||||
|
||||
|
||||
@@ -44,12 +44,11 @@ enum emulation_result {
|
||||
EMULATE_DO_DCR, /* kvm_run filled with DCR request */
|
||||
EMULATE_FAIL, /* can't emulate this instruction */
|
||||
EMULATE_AGAIN, /* something went wrong. go again */
|
||||
EMULATE_DO_PAPR, /* kvm_run filled with PAPR request */
|
||||
};
|
||||
|
||||
extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
|
||||
extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
|
||||
extern char kvmppc_handlers_start[];
|
||||
extern unsigned long kvmppc_handler_len;
|
||||
extern void kvmppc_handler_highmem(void);
|
||||
|
||||
extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu);
|
||||
@@ -263,6 +262,15 @@ static inline void kvm_linear_init(void)
|
||||
{}
|
||||
#endif
|
||||
|
||||
static inline void kvmppc_set_epr(struct kvm_vcpu *vcpu, u32 epr)
|
||||
{
|
||||
#ifdef CONFIG_KVM_BOOKE_HV
|
||||
mtspr(SPRN_GEPR, epr);
|
||||
#elif defined(CONFIG_BOOKE)
|
||||
vcpu->arch.epr = epr;
|
||||
#endif
|
||||
}
|
||||
|
||||
int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
|
||||
struct kvm_config_tlb *cfg);
|
||||
int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu,
|
||||
|
||||
@@ -956,8 +956,6 @@
|
||||
#define SPRN_SPRG_RSCRATCH_DBG SPRN_SPRG9
|
||||
#define SPRN_SPRG_WSCRATCH_DBG SPRN_SPRG9
|
||||
#endif
|
||||
#define SPRN_SPRG_RVCPU SPRN_SPRG1
|
||||
#define SPRN_SPRG_WVCPU SPRN_SPRG1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_8xx
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#define SPRN_SPRG7W 0x117 /* Special Purpose Register General 7 Write */
|
||||
#define SPRN_EPCR 0x133 /* Embedded Processor Control Register */
|
||||
#define SPRN_DBCR2 0x136 /* Debug Control Register 2 */
|
||||
#define SPRN_DBCR4 0x233 /* Debug Control Register 4 */
|
||||
#define SPRN_MSRP 0x137 /* MSR Protect Register */
|
||||
#define SPRN_IAC3 0x13A /* Instruction Address Compare 3 */
|
||||
#define SPRN_IAC4 0x13B /* Instruction Address Compare 4 */
|
||||
|
||||
@@ -114,7 +114,10 @@ struct kvm_regs {
|
||||
/* Embedded Floating Point (SPE) -- IVOR32-34 if KVM_SREGS_E_IVOR */
|
||||
#define KVM_SREGS_E_SPE (1 << 9)
|
||||
|
||||
/* External Proxy (EXP) -- EPR */
|
||||
/*
|
||||
* DEPRECATED! USE ONE_REG FOR THIS ONE!
|
||||
* External Proxy (EXP) -- EPR
|
||||
*/
|
||||
#define KVM_SREGS_EXP (1 << 10)
|
||||
|
||||
/* External PID (E.PD) -- EPSC/EPLC */
|
||||
@@ -412,5 +415,6 @@ struct kvm_get_htab_header {
|
||||
#define KVM_REG_PPC_VPA_DTL (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x84)
|
||||
|
||||
#define KVM_REG_PPC_EPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x85)
|
||||
#define KVM_REG_PPC_EPR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x86)
|
||||
|
||||
#endif /* __LINUX_KVM_POWERPC_H */
|
||||
|
||||
@@ -118,7 +118,7 @@ int main(void)
|
||||
#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
|
||||
DEFINE(THREAD_KVM_SVCPU, offsetof(struct thread_struct, kvm_shadow_vcpu));
|
||||
#endif
|
||||
#ifdef CONFIG_KVM_BOOKE_HV
|
||||
#if defined(CONFIG_KVM) && defined(CONFIG_BOOKE)
|
||||
DEFINE(THREAD_KVM_VCPU, offsetof(struct thread_struct, kvm_vcpu));
|
||||
#endif
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o \
|
||||
eventfd.o)
|
||||
|
||||
CFLAGS_44x_tlb.o := -I.
|
||||
CFLAGS_e500_tlb.o := -I.
|
||||
CFLAGS_e500_mmu.o := -I.
|
||||
CFLAGS_e500_mmu_host.o := -I.
|
||||
CFLAGS_emulate.o := -I.
|
||||
|
||||
common-objs-y += powerpc.o emulate.o
|
||||
@@ -35,7 +36,8 @@ kvm-e500-objs := \
|
||||
booke_emulate.o \
|
||||
booke_interrupts.o \
|
||||
e500.o \
|
||||
e500_tlb.o \
|
||||
e500_mmu.o \
|
||||
e500_mmu_host.o \
|
||||
e500_emulate.o
|
||||
kvm-objs-$(CONFIG_KVM_E500V2) := $(kvm-e500-objs)
|
||||
|
||||
@@ -45,7 +47,8 @@ kvm-e500mc-objs := \
|
||||
booke_emulate.o \
|
||||
bookehv_interrupts.o \
|
||||
e500mc.o \
|
||||
e500_tlb.o \
|
||||
e500_mmu.o \
|
||||
e500_mmu_host.o \
|
||||
e500_emulate.o
|
||||
kvm-objs-$(CONFIG_KVM_E500MC) := $(kvm-e500mc-objs)
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#define OP_31_XOP_MTSRIN 242
|
||||
#define OP_31_XOP_TLBIEL 274
|
||||
#define OP_31_XOP_TLBIE 306
|
||||
/* Opcode is officially reserved, reuse it as sc 1 when sc 1 doesn't trap */
|
||||
#define OP_31_XOP_FAKE_SC1 308
|
||||
#define OP_31_XOP_SLBMTE 402
|
||||
#define OP_31_XOP_SLBIE 434
|
||||
#define OP_31_XOP_SLBIA 498
|
||||
@@ -170,6 +172,32 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
vcpu->arch.mmu.tlbie(vcpu, addr, large);
|
||||
break;
|
||||
}
|
||||
#ifdef CONFIG_KVM_BOOK3S_64_PR
|
||||
case OP_31_XOP_FAKE_SC1:
|
||||
{
|
||||
/* SC 1 papr hypercalls */
|
||||
ulong cmd = kvmppc_get_gpr(vcpu, 3);
|
||||
int i;
|
||||
|
||||
if ((vcpu->arch.shared->msr & MSR_PR) ||
|
||||
!vcpu->arch.papr_enabled) {
|
||||
emulated = EMULATE_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (kvmppc_h_pr(vcpu, cmd) == EMULATE_DONE)
|
||||
break;
|
||||
|
||||
run->papr_hcall.nr = cmd;
|
||||
for (i = 0; i < 9; ++i) {
|
||||
ulong gpr = kvmppc_get_gpr(vcpu, 4 + i);
|
||||
run->papr_hcall.args[i] = gpr;
|
||||
}
|
||||
|
||||
emulated = EMULATE_DO_PAPR;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case OP_31_XOP_EIOIO:
|
||||
break;
|
||||
case OP_31_XOP_SLBMTE:
|
||||
@@ -427,6 +455,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
|
||||
case SPRN_PMC3_GEKKO:
|
||||
case SPRN_PMC4_GEKKO:
|
||||
case SPRN_WPAR_GEKKO:
|
||||
case SPRN_MSSSR0:
|
||||
break;
|
||||
unprivileged:
|
||||
default:
|
||||
@@ -523,6 +552,7 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
|
||||
case SPRN_PMC3_GEKKO:
|
||||
case SPRN_PMC4_GEKKO:
|
||||
case SPRN_WPAR_GEKKO:
|
||||
case SPRN_MSSSR0:
|
||||
*spr_val = 0;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -1549,7 +1549,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
|
||||
mutex_lock(&kvm->slots_lock);
|
||||
|
||||
r = -EINVAL;
|
||||
if (log->slot >= KVM_MEMORY_SLOTS)
|
||||
if (log->slot >= KVM_USER_MEM_SLOTS)
|
||||
goto out;
|
||||
|
||||
memslot = id_to_memslot(kvm->memslots, log->slot);
|
||||
|
||||
@@ -762,6 +762,11 @@ program_interrupt:
|
||||
run->exit_reason = KVM_EXIT_MMIO;
|
||||
r = RESUME_HOST_NV;
|
||||
break;
|
||||
case EMULATE_DO_PAPR:
|
||||
run->exit_reason = KVM_EXIT_PAPR_HCALL;
|
||||
vcpu->arch.hcall_needed = 1;
|
||||
r = RESUME_HOST_NV;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
@@ -182,6 +182,14 @@ static void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu,
|
||||
kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_INST_STORAGE);
|
||||
}
|
||||
|
||||
static void kvmppc_core_queue_alignment(struct kvm_vcpu *vcpu, ulong dear_flags,
|
||||
ulong esr_flags)
|
||||
{
|
||||
vcpu->arch.queued_dear = dear_flags;
|
||||
vcpu->arch.queued_esr = esr_flags;
|
||||
kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ALIGNMENT);
|
||||
}
|
||||
|
||||
void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong esr_flags)
|
||||
{
|
||||
vcpu->arch.queued_esr = esr_flags;
|
||||
@@ -300,13 +308,22 @@ static void set_guest_esr(struct kvm_vcpu *vcpu, u32 esr)
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned long get_guest_epr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
#ifdef CONFIG_KVM_BOOKE_HV
|
||||
return mfspr(SPRN_GEPR);
|
||||
#else
|
||||
return vcpu->arch.epr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Deliver the interrupt of the corresponding priority, if possible. */
|
||||
static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
|
||||
unsigned int priority)
|
||||
{
|
||||
int allowed = 0;
|
||||
ulong msr_mask = 0;
|
||||
bool update_esr = false, update_dear = false;
|
||||
bool update_esr = false, update_dear = false, update_epr = false;
|
||||
ulong crit_raw = vcpu->arch.shared->critical;
|
||||
ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
|
||||
bool crit;
|
||||
@@ -330,9 +347,13 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
|
||||
keep_irq = true;
|
||||
}
|
||||
|
||||
if ((priority == BOOKE_IRQPRIO_EXTERNAL) && vcpu->arch.epr_enabled)
|
||||
update_epr = true;
|
||||
|
||||
switch (priority) {
|
||||
case BOOKE_IRQPRIO_DTLB_MISS:
|
||||
case BOOKE_IRQPRIO_DATA_STORAGE:
|
||||
case BOOKE_IRQPRIO_ALIGNMENT:
|
||||
update_dear = true;
|
||||
/* fall through */
|
||||
case BOOKE_IRQPRIO_INST_STORAGE:
|
||||
@@ -346,7 +367,6 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
|
||||
case BOOKE_IRQPRIO_SPE_FP_DATA:
|
||||
case BOOKE_IRQPRIO_SPE_FP_ROUND:
|
||||
case BOOKE_IRQPRIO_AP_UNAVAIL:
|
||||
case BOOKE_IRQPRIO_ALIGNMENT:
|
||||
allowed = 1;
|
||||
msr_mask = MSR_CE | MSR_ME | MSR_DE;
|
||||
int_class = INT_CLASS_NONCRIT;
|
||||
@@ -408,6 +428,8 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
|
||||
set_guest_esr(vcpu, vcpu->arch.queued_esr);
|
||||
if (update_dear == true)
|
||||
set_guest_dear(vcpu, vcpu->arch.queued_dear);
|
||||
if (update_epr == true)
|
||||
kvm_make_request(KVM_REQ_EPR_EXIT, vcpu);
|
||||
|
||||
new_msr &= msr_mask;
|
||||
#if defined(CONFIG_64BIT)
|
||||
@@ -581,6 +603,11 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
|
||||
|
||||
kvmppc_core_check_exceptions(vcpu);
|
||||
|
||||
if (vcpu->requests) {
|
||||
/* Exception delivery raised request; start over */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vcpu->arch.shared->msr & MSR_WE) {
|
||||
local_irq_enable();
|
||||
kvm_vcpu_block(vcpu);
|
||||
@@ -610,6 +637,13 @@ int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (kvm_check_request(KVM_REQ_EPR_EXIT, vcpu)) {
|
||||
vcpu->run->epr.epr = 0;
|
||||
vcpu->arch.epr_needed = true;
|
||||
vcpu->run->exit_reason = KVM_EXIT_EPR;
|
||||
r = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -945,6 +979,12 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
r = RESUME_GUEST;
|
||||
break;
|
||||
|
||||
case BOOKE_INTERRUPT_ALIGNMENT:
|
||||
kvmppc_core_queue_alignment(vcpu, vcpu->arch.fault_dear,
|
||||
vcpu->arch.fault_esr);
|
||||
r = RESUME_GUEST;
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_KVM_BOOKE_HV
|
||||
case BOOKE_INTERRUPT_HV_SYSCALL:
|
||||
if (!(vcpu->arch.shared->msr & MSR_PR)) {
|
||||
@@ -1388,6 +1428,11 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
|
||||
&vcpu->arch.dbg_reg.dac[dac], sizeof(u64));
|
||||
break;
|
||||
}
|
||||
case KVM_REG_PPC_EPR: {
|
||||
u32 epr = get_guest_epr(vcpu);
|
||||
r = put_user(epr, (u32 __user *)(long)reg->addr);
|
||||
break;
|
||||
}
|
||||
#if defined(CONFIG_64BIT)
|
||||
case KVM_REG_PPC_EPCR:
|
||||
r = put_user(vcpu->arch.epcr, (u32 __user *)(long)reg->addr);
|
||||
@@ -1420,6 +1465,13 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
|
||||
(u64 __user *)(long)reg->addr, sizeof(u64));
|
||||
break;
|
||||
}
|
||||
case KVM_REG_PPC_EPR: {
|
||||
u32 new_epr;
|
||||
r = get_user(new_epr, (u32 __user *)(long)reg->addr);
|
||||
if (!r)
|
||||
kvmppc_set_epr(vcpu, new_epr);
|
||||
break;
|
||||
}
|
||||
#if defined(CONFIG_64BIT)
|
||||
case KVM_REG_PPC_EPCR: {
|
||||
u32 new_epcr;
|
||||
@@ -1556,7 +1608,9 @@ int __init kvmppc_booke_init(void)
|
||||
{
|
||||
#ifndef CONFIG_KVM_BOOKE_HV
|
||||
unsigned long ivor[16];
|
||||
unsigned long *handler = kvmppc_booke_handler_addr;
|
||||
unsigned long max_ivor = 0;
|
||||
unsigned long handler_len;
|
||||
int i;
|
||||
|
||||
/* We install our own exception handlers by hijacking IVPR. IVPR must
|
||||
@@ -1589,14 +1643,16 @@ int __init kvmppc_booke_init(void)
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (ivor[i] > max_ivor)
|
||||
max_ivor = ivor[i];
|
||||
max_ivor = i;
|
||||
|
||||
handler_len = handler[i + 1] - handler[i];
|
||||
memcpy((void *)kvmppc_booke_handlers + ivor[i],
|
||||
kvmppc_handlers_start + i * kvmppc_handler_len,
|
||||
kvmppc_handler_len);
|
||||
(void *)handler[i], handler_len);
|
||||
}
|
||||
flush_icache_range(kvmppc_booke_handlers,
|
||||
kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
|
||||
|
||||
handler_len = handler[max_ivor + 1] - handler[max_ivor];
|
||||
flush_icache_range(kvmppc_booke_handlers, kvmppc_booke_handlers +
|
||||
ivor[max_ivor] + handler_len);
|
||||
#endif /* !BOOKE_HV */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
(1 << BOOKE_IRQPRIO_CRITICAL))
|
||||
|
||||
extern unsigned long kvmppc_booke_handlers;
|
||||
extern unsigned long kvmppc_booke_handler_addr[];
|
||||
|
||||
void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr);
|
||||
void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr);
|
||||
|
||||
@@ -269,6 +269,9 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
|
||||
case SPRN_ESR:
|
||||
*spr_val = vcpu->arch.shared->esr;
|
||||
break;
|
||||
case SPRN_EPR:
|
||||
*spr_val = vcpu->arch.epr;
|
||||
break;
|
||||
case SPRN_CSRR0:
|
||||
*spr_val = vcpu->arch.csrr0;
|
||||
break;
|
||||
|
||||
@@ -45,18 +45,21 @@
|
||||
(1<<BOOKE_INTERRUPT_DEBUG))
|
||||
|
||||
#define NEED_DEAR_MASK ((1<<BOOKE_INTERRUPT_DATA_STORAGE) | \
|
||||
(1<<BOOKE_INTERRUPT_DTLB_MISS))
|
||||
(1<<BOOKE_INTERRUPT_DTLB_MISS) | \
|
||||
(1<<BOOKE_INTERRUPT_ALIGNMENT))
|
||||
|
||||
#define NEED_ESR_MASK ((1<<BOOKE_INTERRUPT_DATA_STORAGE) | \
|
||||
(1<<BOOKE_INTERRUPT_INST_STORAGE) | \
|
||||
(1<<BOOKE_INTERRUPT_PROGRAM) | \
|
||||
(1<<BOOKE_INTERRUPT_DTLB_MISS))
|
||||
(1<<BOOKE_INTERRUPT_DTLB_MISS) | \
|
||||
(1<<BOOKE_INTERRUPT_ALIGNMENT))
|
||||
|
||||
.macro KVM_HANDLER ivor_nr scratch srr0
|
||||
_GLOBAL(kvmppc_handler_\ivor_nr)
|
||||
/* Get pointer to vcpu and record exit number. */
|
||||
mtspr \scratch , r4
|
||||
mfspr r4, SPRN_SPRG_RVCPU
|
||||
mfspr r4, SPRN_SPRG_THREAD
|
||||
lwz r4, THREAD_KVM_VCPU(r4)
|
||||
stw r3, VCPU_GPR(R3)(r4)
|
||||
stw r5, VCPU_GPR(R5)(r4)
|
||||
stw r6, VCPU_GPR(R6)(r4)
|
||||
@@ -73,6 +76,14 @@ _GLOBAL(kvmppc_handler_\ivor_nr)
|
||||
bctr
|
||||
.endm
|
||||
|
||||
.macro KVM_HANDLER_ADDR ivor_nr
|
||||
.long kvmppc_handler_\ivor_nr
|
||||
.endm
|
||||
|
||||
.macro KVM_HANDLER_END
|
||||
.long kvmppc_handlers_end
|
||||
.endm
|
||||
|
||||
_GLOBAL(kvmppc_handlers_start)
|
||||
KVM_HANDLER BOOKE_INTERRUPT_CRITICAL SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
|
||||
KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK SPRN_SPRG_RSCRATCH_MC SPRN_MCSRR0
|
||||
@@ -93,9 +104,7 @@ KVM_HANDLER BOOKE_INTERRUPT_DEBUG SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
|
||||
KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL SPRN_SPRG_RSCRATCH0 SPRN_SRR0
|
||||
KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA SPRN_SPRG_RSCRATCH0 SPRN_SRR0
|
||||
KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_ROUND SPRN_SPRG_RSCRATCH0 SPRN_SRR0
|
||||
|
||||
_GLOBAL(kvmppc_handler_len)
|
||||
.long kvmppc_handler_1 - kvmppc_handler_0
|
||||
_GLOBAL(kvmppc_handlers_end)
|
||||
|
||||
/* Registers:
|
||||
* SPRG_SCRATCH0: guest r4
|
||||
@@ -402,9 +411,6 @@ lightweight_exit:
|
||||
lwz r8, kvmppc_booke_handlers@l(r8)
|
||||
mtspr SPRN_IVPR, r8
|
||||
|
||||
/* Save vcpu pointer for the exception handlers. */
|
||||
mtspr SPRN_SPRG_WVCPU, r4
|
||||
|
||||
lwz r5, VCPU_SHARED(r4)
|
||||
|
||||
/* Can't switch the stack pointer until after IVPR is switched,
|
||||
@@ -463,6 +469,31 @@ lightweight_exit:
|
||||
lwz r4, VCPU_GPR(R4)(r4)
|
||||
rfi
|
||||
|
||||
.data
|
||||
.align 4
|
||||
.globl kvmppc_booke_handler_addr
|
||||
kvmppc_booke_handler_addr:
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_CRITICAL
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_MACHINE_CHECK
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_DATA_STORAGE
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_INST_STORAGE
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_EXTERNAL
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_ALIGNMENT
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_PROGRAM
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_FP_UNAVAIL
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_SYSCALL
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_AP_UNAVAIL
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_DECREMENTER
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_FIT
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_WATCHDOG
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_DTLB_MISS
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_ITLB_MISS
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_DEBUG
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_UNAVAIL
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_FP_DATA
|
||||
KVM_HANDLER_ADDR BOOKE_INTERRUPT_SPE_FP_ROUND
|
||||
KVM_HANDLER_END /*Always keep this in end*/
|
||||
|
||||
#ifdef CONFIG_SPE
|
||||
_GLOBAL(kvmppc_save_guest_spe)
|
||||
cmpi 0,r3,0
|
||||
|
||||
+10
-6
@@ -491,6 +491,9 @@ static int __init kvmppc_e500_init(void)
|
||||
{
|
||||
int r, i;
|
||||
unsigned long ivor[3];
|
||||
/* Process remaining handlers above the generic first 16 */
|
||||
unsigned long *handler = &kvmppc_booke_handler_addr[16];
|
||||
unsigned long handler_len;
|
||||
unsigned long max_ivor = 0;
|
||||
|
||||
r = kvmppc_core_check_processor_compat();
|
||||
@@ -506,15 +509,16 @@ static int __init kvmppc_e500_init(void)
|
||||
ivor[1] = mfspr(SPRN_IVOR33);
|
||||
ivor[2] = mfspr(SPRN_IVOR34);
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (ivor[i] > max_ivor)
|
||||
max_ivor = ivor[i];
|
||||
if (ivor[i] > ivor[max_ivor])
|
||||
max_ivor = i;
|
||||
|
||||
handler_len = handler[i + 1] - handler[i];
|
||||
memcpy((void *)kvmppc_booke_handlers + ivor[i],
|
||||
kvmppc_handlers_start + (i + 16) * kvmppc_handler_len,
|
||||
kvmppc_handler_len);
|
||||
(void *)handler[i], handler_len);
|
||||
}
|
||||
flush_icache_range(kvmppc_booke_handlers,
|
||||
kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
|
||||
handler_len = handler[max_ivor + 1] - handler[max_ivor];
|
||||
flush_icache_range(kvmppc_booke_handlers, kvmppc_booke_handlers +
|
||||
ivor[max_ivor] + handler_len);
|
||||
|
||||
return kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), 0, THIS_MODULE);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user