mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 17:43:52 +02:00
Merge branch 'topic/ppc-kvm' into next
This commit is contained in:
commit
ba6d8efb1b
|
|
@ -193,6 +193,7 @@ static inline void cpu_feature_keys_init(void) { }
|
|||
#define CPU_FTR_ARCH_31 LONG_ASM_CONST(0x0004000000000000)
|
||||
#define CPU_FTR_DAWR1 LONG_ASM_CONST(0x0008000000000000)
|
||||
#define CPU_FTR_DEXCR_NPHIE LONG_ASM_CONST(0x0010000000000000)
|
||||
#define CPU_FTR_P11_PVR LONG_ASM_CONST(0x0020000000000000)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
|
|
@ -454,7 +455,7 @@ static inline void cpu_feature_keys_init(void) { }
|
|||
CPU_FTR_DAWR | CPU_FTR_DAWR1 | \
|
||||
CPU_FTR_DEXCR_NPHIE)
|
||||
|
||||
#define CPU_FTRS_POWER11 CPU_FTRS_POWER10
|
||||
#define CPU_FTRS_POWER11 (CPU_FTRS_POWER10 | CPU_FTR_P11_PVR)
|
||||
|
||||
#define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
|
||||
|
|
@ -475,7 +476,7 @@ static inline void cpu_feature_keys_init(void) { }
|
|||
(CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 | \
|
||||
CPU_FTR_ALTIVEC_COMP | CPU_FTR_VSX_COMP | CPU_FTRS_POWER9 | \
|
||||
CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | \
|
||||
CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10)
|
||||
CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10 | CPU_FTRS_POWER11)
|
||||
#else
|
||||
#define CPU_FTRS_POSSIBLE \
|
||||
(CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \
|
||||
|
|
@ -483,7 +484,7 @@ static inline void cpu_feature_keys_init(void) { }
|
|||
CPU_FTRS_POWER8 | CPU_FTRS_CELL | CPU_FTRS_PA6T | \
|
||||
CPU_FTR_VSX_COMP | CPU_FTR_ALTIVEC_COMP | CPU_FTRS_POWER9 | \
|
||||
CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | \
|
||||
CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10)
|
||||
CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10 | CPU_FTRS_POWER11)
|
||||
#endif /* CONFIG_CPU_LITTLE_ENDIAN */
|
||||
#endif
|
||||
#else
|
||||
|
|
@ -547,7 +548,7 @@ enum {
|
|||
(CPU_FTRS_POSSIBLE & ~CPU_FTR_HVMODE & ~CPU_FTR_DBELL & \
|
||||
CPU_FTRS_POWER7 & CPU_FTRS_POWER8E & CPU_FTRS_POWER8 & \
|
||||
CPU_FTRS_POWER9 & CPU_FTRS_POWER9_DD2_1 & CPU_FTRS_POWER9_DD2_2 & \
|
||||
CPU_FTRS_POWER10 & CPU_FTRS_DT_CPU_BASE)
|
||||
CPU_FTRS_POWER10 & CPU_FTRS_POWER11 & CPU_FTRS_DT_CPU_BASE)
|
||||
#else
|
||||
#define CPU_FTRS_ALWAYS \
|
||||
(CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & \
|
||||
|
|
@ -555,7 +556,7 @@ enum {
|
|||
CPU_FTRS_PA6T & CPU_FTRS_POWER8 & CPU_FTRS_POWER8E & \
|
||||
~CPU_FTR_HVMODE & ~CPU_FTR_DBELL & CPU_FTRS_POSSIBLE & \
|
||||
CPU_FTRS_POWER9 & CPU_FTRS_POWER9_DD2_1 & CPU_FTRS_POWER9_DD2_2 & \
|
||||
CPU_FTRS_POWER10 & CPU_FTRS_DT_CPU_BASE)
|
||||
CPU_FTRS_POWER10 & CPU_FTRS_POWER11 & CPU_FTRS_DT_CPU_BASE)
|
||||
#endif /* CONFIG_CPU_LITTLE_ENDIAN */
|
||||
#endif
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -495,6 +495,7 @@
|
|||
#define H_GUEST_CAP_COPY_MEM (1UL<<(63-0))
|
||||
#define H_GUEST_CAP_POWER9 (1UL<<(63-1))
|
||||
#define H_GUEST_CAP_POWER10 (1UL<<(63-2))
|
||||
#define H_GUEST_CAP_POWER11 (1UL<<(63-3))
|
||||
#define H_GUEST_CAP_BITMAP2 (1UL<<(63-63))
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
|
|
|||
|
|
@ -684,8 +684,8 @@ int kvmhv_nestedv2_set_ptbl_entry(unsigned long lpid, u64 dw0, u64 dw1);
|
|||
int kvmhv_nestedv2_parse_output(struct kvm_vcpu *vcpu);
|
||||
int kvmhv_nestedv2_set_vpa(struct kvm_vcpu *vcpu, unsigned long vpa);
|
||||
|
||||
int kmvhv_counters_tracepoint_regfunc(void);
|
||||
void kmvhv_counters_tracepoint_unregfunc(void);
|
||||
int kvmhv_counters_tracepoint_regfunc(void);
|
||||
void kvmhv_counters_tracepoint_unregfunc(void);
|
||||
int kvmhv_get_l2_counters_status(void);
|
||||
void kvmhv_set_l2_counters_status(int cpu, bool status);
|
||||
|
||||
|
|
|
|||
|
|
@ -400,7 +400,10 @@ static inline unsigned long map_pcr_to_cap(unsigned long pcr)
|
|||
cap = H_GUEST_CAP_POWER9;
|
||||
break;
|
||||
case PCR_ARCH_31:
|
||||
cap = H_GUEST_CAP_POWER10;
|
||||
if (cpu_has_feature(CPU_FTR_P11_PVR))
|
||||
cap = H_GUEST_CAP_POWER11;
|
||||
else
|
||||
cap = H_GUEST_CAP_POWER10;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -415,7 +418,7 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
|
|||
struct kvmppc_vcore *vc = vcpu->arch.vcore;
|
||||
|
||||
/* We can (emulate) our own architecture version and anything older */
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_31))
|
||||
if (cpu_has_feature(CPU_FTR_P11_PVR) || cpu_has_feature(CPU_FTR_ARCH_31))
|
||||
host_pcr_bit = PCR_ARCH_31;
|
||||
else if (cpu_has_feature(CPU_FTR_ARCH_300))
|
||||
host_pcr_bit = PCR_ARCH_300;
|
||||
|
|
@ -2060,36 +2063,9 @@ static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu)
|
|||
fallthrough; /* go to facility unavailable handler */
|
||||
#endif
|
||||
|
||||
case BOOK3S_INTERRUPT_H_FAC_UNAVAIL: {
|
||||
u64 cause = vcpu->arch.hfscr >> 56;
|
||||
|
||||
/*
|
||||
* Only pass HFU interrupts to the L1 if the facility is
|
||||
* permitted but disabled by the L1's HFSCR, otherwise
|
||||
* the interrupt does not make sense to the L1 so turn
|
||||
* it into a HEAI.
|
||||
*/
|
||||
if (!(vcpu->arch.hfscr_permitted & (1UL << cause)) ||
|
||||
(vcpu->arch.nested_hfscr & (1UL << cause))) {
|
||||
ppc_inst_t pinst;
|
||||
vcpu->arch.trap = BOOK3S_INTERRUPT_H_EMUL_ASSIST;
|
||||
|
||||
/*
|
||||
* If the fetch failed, return to guest and
|
||||
* try executing it again.
|
||||
*/
|
||||
r = kvmppc_get_last_inst(vcpu, INST_GENERIC, &pinst);
|
||||
vcpu->arch.emul_inst = ppc_inst_val(pinst);
|
||||
if (r != EMULATE_DONE)
|
||||
r = RESUME_GUEST;
|
||||
else
|
||||
r = RESUME_HOST;
|
||||
} else {
|
||||
r = RESUME_HOST;
|
||||
}
|
||||
|
||||
case BOOK3S_INTERRUPT_H_FAC_UNAVAIL:
|
||||
r = RESUME_HOST;
|
||||
break;
|
||||
}
|
||||
|
||||
case BOOK3S_INTERRUPT_HV_RM_HARD:
|
||||
vcpu->arch.trap = 0;
|
||||
|
|
@ -4154,7 +4130,7 @@ void kvmhv_set_l2_counters_status(int cpu, bool status)
|
|||
lppaca_of(cpu).l2_counters_enable = 0;
|
||||
}
|
||||
|
||||
int kmvhv_counters_tracepoint_regfunc(void)
|
||||
int kvmhv_counters_tracepoint_regfunc(void)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
|
|
@ -4164,7 +4140,7 @@ int kmvhv_counters_tracepoint_regfunc(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void kmvhv_counters_tracepoint_unregfunc(void)
|
||||
void kvmhv_counters_tracepoint_unregfunc(void)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
|
|
@ -4309,6 +4285,15 @@ static int kvmhv_vcpu_entry_p9_nested(struct kvm_vcpu *vcpu, u64 time_limit, uns
|
|||
}
|
||||
hvregs.hdec_expiry = time_limit;
|
||||
|
||||
/*
|
||||
* hvregs has the doorbell status, so zero it here which
|
||||
* enables us to receive doorbells when H_ENTER_NESTED is
|
||||
* in progress for this vCPU
|
||||
*/
|
||||
|
||||
if (vcpu->arch.doorbell_request)
|
||||
vcpu->arch.doorbell_request = 0;
|
||||
|
||||
/*
|
||||
* When setting DEC, we must always deal with irq_work_raise
|
||||
* via NMI vs setting DEC. The problem occurs right as we
|
||||
|
|
@ -4900,7 +4885,6 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
|
|||
lpcr |= LPCR_MER;
|
||||
}
|
||||
} else if (vcpu->arch.pending_exceptions ||
|
||||
vcpu->arch.doorbell_request ||
|
||||
xive_interrupt_pending(vcpu)) {
|
||||
vcpu->arch.ret = RESUME_HOST;
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ void kvmhv_save_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr)
|
|||
struct kvmppc_vcore *vc = vcpu->arch.vcore;
|
||||
|
||||
hr->pcr = vc->pcr | PCR_MASK;
|
||||
hr->dpdes = vc->dpdes;
|
||||
hr->dpdes = vcpu->arch.doorbell_request;
|
||||
hr->hfscr = vcpu->arch.hfscr;
|
||||
hr->tb_offset = vc->tb_offset;
|
||||
hr->dawr0 = vcpu->arch.dawr0;
|
||||
|
|
@ -105,7 +105,7 @@ static void save_hv_return_state(struct kvm_vcpu *vcpu,
|
|||
{
|
||||
struct kvmppc_vcore *vc = vcpu->arch.vcore;
|
||||
|
||||
hr->dpdes = vc->dpdes;
|
||||
hr->dpdes = vcpu->arch.doorbell_request;
|
||||
hr->purr = vcpu->arch.purr;
|
||||
hr->spurr = vcpu->arch.spurr;
|
||||
hr->ic = vcpu->arch.ic;
|
||||
|
|
@ -143,7 +143,7 @@ static void restore_hv_regs(struct kvm_vcpu *vcpu, const struct hv_guest_state *
|
|||
struct kvmppc_vcore *vc = vcpu->arch.vcore;
|
||||
|
||||
vc->pcr = hr->pcr | PCR_MASK;
|
||||
vc->dpdes = hr->dpdes;
|
||||
vcpu->arch.doorbell_request = hr->dpdes;
|
||||
vcpu->arch.hfscr = hr->hfscr;
|
||||
vcpu->arch.dawr0 = hr->dawr0;
|
||||
vcpu->arch.dawrx0 = hr->dawrx0;
|
||||
|
|
@ -170,7 +170,13 @@ void kvmhv_restore_hv_return_state(struct kvm_vcpu *vcpu,
|
|||
{
|
||||
struct kvmppc_vcore *vc = vcpu->arch.vcore;
|
||||
|
||||
vc->dpdes = hr->dpdes;
|
||||
/*
|
||||
* This L2 vCPU might have received a doorbell while H_ENTER_NESTED was being handled.
|
||||
* Make sure we preserve the doorbell if it was either:
|
||||
* a) Sent after H_ENTER_NESTED was called on this vCPU (arch.doorbell_request would be 1)
|
||||
* b) Doorbell was not handled and L2 exited for some other reason (hr->dpdes would be 1)
|
||||
*/
|
||||
vcpu->arch.doorbell_request = vcpu->arch.doorbell_request | hr->dpdes;
|
||||
vcpu->arch.hfscr = hr->hfscr;
|
||||
vcpu->arch.purr = hr->purr;
|
||||
vcpu->arch.spurr = hr->spurr;
|
||||
|
|
@ -445,6 +451,8 @@ long kvmhv_nested_init(void)
|
|||
if (rc == H_SUCCESS) {
|
||||
unsigned long capabilities = 0;
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_P11_PVR))
|
||||
capabilities |= H_GUEST_CAP_POWER11;
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_31))
|
||||
capabilities |= H_GUEST_CAP_POWER10;
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_300))
|
||||
|
|
|
|||
|
|
@ -370,7 +370,9 @@ static int gs_msg_ops_vcpu_fill_info(struct kvmppc_gs_buff *gsb,
|
|||
* default to L1's PVR.
|
||||
*/
|
||||
if (!vcpu->arch.vcore->arch_compat) {
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_31))
|
||||
if (cpu_has_feature(CPU_FTR_P11_PVR))
|
||||
arch_compat = PVR_ARCH_31_P11;
|
||||
else if (cpu_has_feature(CPU_FTR_ARCH_31))
|
||||
arch_compat = PVR_ARCH_31;
|
||||
else if (cpu_has_feature(CPU_FTR_ARCH_300))
|
||||
arch_compat = PVR_ARCH_300;
|
||||
|
|
|
|||
|
|
@ -92,12 +92,6 @@ void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
|
|||
spin_unlock(&vcpu3s->mmu_lock);
|
||||
}
|
||||
|
||||
static void free_pte_rcu(struct rcu_head *head)
|
||||
{
|
||||
struct hpte_cache *pte = container_of(head, struct hpte_cache, rcu_head);
|
||||
kmem_cache_free(hpte_cache, pte);
|
||||
}
|
||||
|
||||
static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
|
||||
{
|
||||
struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
|
||||
|
|
@ -126,7 +120,7 @@ static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
|
|||
|
||||
spin_unlock(&vcpu3s->mmu_lock);
|
||||
|
||||
call_rcu(&pte->rcu_head, free_pte_rcu);
|
||||
kfree_rcu(pte, rcu_head);
|
||||
}
|
||||
|
||||
static void kvmppc_mmu_pte_flush_all(struct kvm_vcpu *vcpu)
|
||||
|
|
|
|||
|
|
@ -538,7 +538,7 @@ TRACE_EVENT_FN_COND(kvmppc_vcpu_stats,
|
|||
TP_printk("VCPU %d: l1_to_l2_cs_time=%llu ns l2_to_l1_cs_time=%llu ns l2_runtime=%llu ns",
|
||||
__entry->vcpu_id, __entry->l1_to_l2_cs,
|
||||
__entry->l2_to_l1_cs, __entry->l2_runtime),
|
||||
kmvhv_counters_tracepoint_regfunc, kmvhv_counters_tracepoint_unregfunc
|
||||
kvmhv_counters_tracepoint_regfunc, kvmhv_counters_tracepoint_unregfunc
|
||||
);
|
||||
#endif
|
||||
#endif /* _TRACE_KVM_HV_H */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user