mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 14:42:24 +00:00
KVM: PPC: Book3S HV: Context-switch new POWER8 SPRs
This adds fields to the struct kvm_vcpu_arch to store the new guest-accessible SPRs on POWER8, adds code to the get/set_one_reg functions to allow userspace to access this state, and adds code to the guest entry and exit to context-switch these SPRs between host and guest. Note that DPDES (Directed Privileged Doorbell Exception State) is shared between threads on a core; hence we store it in struct kvmppc_vcore and have the master thread save and restore it. Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
e0b7ec058c
commit
b005255e12
@ -304,6 +304,7 @@ struct kvmppc_vcore {
|
||||
ulong lpcr;
|
||||
u32 arch_compat;
|
||||
ulong pcr;
|
||||
ulong dpdes; /* doorbell state (POWER8) */
|
||||
};
|
||||
|
||||
#define VCORE_ENTRY_COUNT(vc) ((vc)->entry_exit_count & 0xff)
|
||||
@ -448,6 +449,7 @@ struct kvm_vcpu_arch {
|
||||
ulong pc;
|
||||
ulong ctr;
|
||||
ulong lr;
|
||||
ulong tar;
|
||||
|
||||
ulong xer;
|
||||
u32 cr;
|
||||
@ -457,13 +459,32 @@ struct kvm_vcpu_arch {
|
||||
ulong guest_owned_ext;
|
||||
ulong purr;
|
||||
ulong spurr;
|
||||
ulong ic;
|
||||
ulong vtb;
|
||||
ulong dscr;
|
||||
ulong amr;
|
||||
ulong uamor;
|
||||
ulong iamr;
|
||||
u32 ctrl;
|
||||
ulong dabr;
|
||||
ulong dawr;
|
||||
ulong dawrx;
|
||||
ulong ciabr;
|
||||
ulong cfar;
|
||||
ulong ppr;
|
||||
ulong pspb;
|
||||
ulong fscr;
|
||||
ulong tfhar;
|
||||
ulong tfiar;
|
||||
ulong texasr;
|
||||
ulong ebbhr;
|
||||
ulong ebbrr;
|
||||
ulong bescr;
|
||||
ulong csigr;
|
||||
ulong tacr;
|
||||
ulong tcscr;
|
||||
ulong acop;
|
||||
ulong wort;
|
||||
ulong shadow_srr1;
|
||||
#endif
|
||||
u32 vrsave; /* also USPRG0 */
|
||||
@ -498,10 +519,12 @@ struct kvm_vcpu_arch {
|
||||
u32 ccr1;
|
||||
u32 dbsr;
|
||||
|
||||
u64 mmcr[3];
|
||||
u64 mmcr[5];
|
||||
u32 pmc[8];
|
||||
u32 spmc[2];
|
||||
u64 siar;
|
||||
u64 sdar;
|
||||
u64 sier;
|
||||
|
||||
#ifdef CONFIG_KVM_EXIT_TIMING
|
||||
struct mutex exit_timing_lock;
|
||||
|
@ -223,6 +223,11 @@
|
||||
#define CTRL_TE 0x00c00000 /* thread enable */
|
||||
#define CTRL_RUNLATCH 0x1
|
||||
#define SPRN_DAWR 0xB4
|
||||
#define SPRN_CIABR 0xBB
|
||||
#define CIABR_PRIV 0x3
|
||||
#define CIABR_PRIV_USER 1
|
||||
#define CIABR_PRIV_SUPER 2
|
||||
#define CIABR_PRIV_HYPER 3
|
||||
#define SPRN_DAWRX 0xBC
|
||||
#define DAWRX_USER (1UL << 0)
|
||||
#define DAWRX_KERNEL (1UL << 1)
|
||||
@ -260,6 +265,8 @@
|
||||
#define SPRN_HRMOR 0x139 /* Real mode offset register */
|
||||
#define SPRN_HSRR0 0x13A /* Hypervisor Save/Restore 0 */
|
||||
#define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */
|
||||
#define SPRN_IC 0x350 /* Virtual Instruction Count */
|
||||
#define SPRN_VTB 0x351 /* Virtual Time Base */
|
||||
/* HFSCR and FSCR bit numbers are the same */
|
||||
#define FSCR_TAR_LG 8 /* Enable Target Address Register */
|
||||
#define FSCR_EBB_LG 7 /* Enable Event Based Branching */
|
||||
@ -368,6 +375,8 @@
|
||||
#define DER_EBRKE 0x00000002 /* External Breakpoint Interrupt */
|
||||
#define DER_DPIE 0x00000001 /* Dev. Port Nonmaskable Request */
|
||||
#define SPRN_DMISS 0x3D0 /* Data TLB Miss Register */
|
||||
#define SPRN_DHDES 0x0B1 /* Directed Hyp. Doorbell Exc. State */
|
||||
#define SPRN_DPDES 0x0B0 /* Directed Priv. Doorbell Exc. State */
|
||||
#define SPRN_EAR 0x11A /* External Address Register */
|
||||
#define SPRN_HASH1 0x3D2 /* Primary Hash Address Register */
|
||||
#define SPRN_HASH2 0x3D3 /* Secondary Hash Address Resgister */
|
||||
@ -427,6 +436,7 @@
|
||||
#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
|
||||
#define SPRN_IABR2 0x3FA /* 83xx */
|
||||
#define SPRN_IBCR 0x135 /* 83xx Insn Breakpoint Control Reg */
|
||||
#define SPRN_IAMR 0x03D /* Instr. Authority Mask Reg */
|
||||
#define SPRN_HID4 0x3F4 /* 970 HID4 */
|
||||
#define HID4_LPES0 (1ul << (63-0)) /* LPAR env. sel. bit 0 */
|
||||
#define HID4_RMLS2_SH (63 - 2) /* Real mode limit bottom 2 bits */
|
||||
@ -541,6 +551,7 @@
|
||||
#define SPRN_PIR 0x3FF /* Processor Identification Register */
|
||||
#endif
|
||||
#define SPRN_TIR 0x1BE /* Thread Identification Register */
|
||||
#define SPRN_PSPB 0x09F /* Problem State Priority Boost reg */
|
||||
#define SPRN_PTEHI 0x3D5 /* 981 7450 PTE HI word (S/W TLB load) */
|
||||
#define SPRN_PTELO 0x3D6 /* 982 7450 PTE LO word (S/W TLB load) */
|
||||
#define SPRN_PURR 0x135 /* Processor Utilization of Resources Reg */
|
||||
@ -682,6 +693,7 @@
|
||||
#define SPRN_EBBHR 804 /* Event based branch handler register */
|
||||
#define SPRN_EBBRR 805 /* Event based branch return register */
|
||||
#define SPRN_BESCR 806 /* Branch event status and control register */
|
||||
#define SPRN_WORT 895 /* Workload optimization register - thread */
|
||||
|
||||
#define SPRN_PMC1 787
|
||||
#define SPRN_PMC2 788
|
||||
@ -698,6 +710,11 @@
|
||||
#define SIER_SIHV 0x1000000 /* Sampled MSR_HV */
|
||||
#define SIER_SIAR_VALID 0x0400000 /* SIAR contents valid */
|
||||
#define SIER_SDAR_VALID 0x0200000 /* SDAR contents valid */
|
||||
#define SPRN_TACR 888
|
||||
#define SPRN_TCSCR 889
|
||||
#define SPRN_CSIGR 890
|
||||
#define SPRN_SPMC1 892
|
||||
#define SPRN_SPMC2 893
|
||||
|
||||
/* When EBB is enabled, some of MMCR0/MMCR2/SIER are user accessible */
|
||||
#define MMCR0_USER_MASK (MMCR0_FC | MMCR0_PMXE | MMCR0_PMAO)
|
||||
|
@ -545,6 +545,7 @@ struct kvm_get_htab_header {
|
||||
#define KVM_REG_PPC_TCSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb1)
|
||||
#define KVM_REG_PPC_PID (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb2)
|
||||
#define KVM_REG_PPC_ACOP (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb3)
|
||||
#define KVM_REG_PPC_WORT (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb4)
|
||||
|
||||
#define KVM_REG_PPC_VRSAVE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4)
|
||||
#define KVM_REG_PPC_LPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5)
|
||||
|
@ -432,6 +432,7 @@ int main(void)
|
||||
DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
|
||||
DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
|
||||
DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
|
||||
DEFINE(VCPU_TAR, offsetof(struct kvm_vcpu, arch.tar));
|
||||
DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
|
||||
DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
|
||||
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
|
||||
@ -484,11 +485,17 @@ int main(void)
|
||||
DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id));
|
||||
DEFINE(VCPU_PURR, offsetof(struct kvm_vcpu, arch.purr));
|
||||
DEFINE(VCPU_SPURR, offsetof(struct kvm_vcpu, arch.spurr));
|
||||
DEFINE(VCPU_IC, offsetof(struct kvm_vcpu, arch.ic));
|
||||
DEFINE(VCPU_VTB, offsetof(struct kvm_vcpu, arch.vtb));
|
||||
DEFINE(VCPU_DSCR, offsetof(struct kvm_vcpu, arch.dscr));
|
||||
DEFINE(VCPU_AMR, offsetof(struct kvm_vcpu, arch.amr));
|
||||
DEFINE(VCPU_UAMOR, offsetof(struct kvm_vcpu, arch.uamor));
|
||||
DEFINE(VCPU_IAMR, offsetof(struct kvm_vcpu, arch.iamr));
|
||||
DEFINE(VCPU_CTRL, offsetof(struct kvm_vcpu, arch.ctrl));
|
||||
DEFINE(VCPU_DABR, offsetof(struct kvm_vcpu, arch.dabr));
|
||||
DEFINE(VCPU_DAWR, offsetof(struct kvm_vcpu, arch.dawr));
|
||||
DEFINE(VCPU_DAWRX, offsetof(struct kvm_vcpu, arch.dawrx));
|
||||
DEFINE(VCPU_CIABR, offsetof(struct kvm_vcpu, arch.ciabr));
|
||||
DEFINE(VCPU_HFLAGS, offsetof(struct kvm_vcpu, arch.hflags));
|
||||
DEFINE(VCPU_DEC, offsetof(struct kvm_vcpu, arch.dec));
|
||||
DEFINE(VCPU_DEC_EXPIRES, offsetof(struct kvm_vcpu, arch.dec_expires));
|
||||
@ -497,8 +504,10 @@ int main(void)
|
||||
DEFINE(VCPU_PRODDED, offsetof(struct kvm_vcpu, arch.prodded));
|
||||
DEFINE(VCPU_MMCR, offsetof(struct kvm_vcpu, arch.mmcr));
|
||||
DEFINE(VCPU_PMC, offsetof(struct kvm_vcpu, arch.pmc));
|
||||
DEFINE(VCPU_SPMC, offsetof(struct kvm_vcpu, arch.spmc));
|
||||
DEFINE(VCPU_SIAR, offsetof(struct kvm_vcpu, arch.siar));
|
||||
DEFINE(VCPU_SDAR, offsetof(struct kvm_vcpu, arch.sdar));
|
||||
DEFINE(VCPU_SIER, offsetof(struct kvm_vcpu, arch.sier));
|
||||
DEFINE(VCPU_SLB, offsetof(struct kvm_vcpu, arch.slb));
|
||||
DEFINE(VCPU_SLB_MAX, offsetof(struct kvm_vcpu, arch.slb_max));
|
||||
DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr));
|
||||
@ -508,6 +517,19 @@ int main(void)
|
||||
DEFINE(VCPU_TRAP, offsetof(struct kvm_vcpu, arch.trap));
|
||||
DEFINE(VCPU_CFAR, offsetof(struct kvm_vcpu, arch.cfar));
|
||||
DEFINE(VCPU_PPR, offsetof(struct kvm_vcpu, arch.ppr));
|
||||
DEFINE(VCPU_FSCR, offsetof(struct kvm_vcpu, arch.fscr));
|
||||
DEFINE(VCPU_PSPB, offsetof(struct kvm_vcpu, arch.pspb));
|
||||
DEFINE(VCPU_TFHAR, offsetof(struct kvm_vcpu, arch.tfhar));
|
||||
DEFINE(VCPU_TFIAR, offsetof(struct kvm_vcpu, arch.tfiar));
|
||||
DEFINE(VCPU_TEXASR, offsetof(struct kvm_vcpu, arch.texasr));
|
||||
DEFINE(VCPU_EBBHR, offsetof(struct kvm_vcpu, arch.ebbhr));
|
||||
DEFINE(VCPU_EBBRR, offsetof(struct kvm_vcpu, arch.ebbrr));
|
||||
DEFINE(VCPU_BESCR, offsetof(struct kvm_vcpu, arch.bescr));
|
||||
DEFINE(VCPU_CSIGR, offsetof(struct kvm_vcpu, arch.csigr));
|
||||
DEFINE(VCPU_TACR, offsetof(struct kvm_vcpu, arch.tacr));
|
||||
DEFINE(VCPU_TCSCR, offsetof(struct kvm_vcpu, arch.tcscr));
|
||||
DEFINE(VCPU_ACOP, offsetof(struct kvm_vcpu, arch.acop));
|
||||
DEFINE(VCPU_WORT, offsetof(struct kvm_vcpu, arch.wort));
|
||||
DEFINE(VCPU_SHADOW_SRR1, offsetof(struct kvm_vcpu, arch.shadow_srr1));
|
||||
DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_count));
|
||||
DEFINE(VCORE_NAP_COUNT, offsetof(struct kvmppc_vcore, nap_count));
|
||||
@ -517,6 +539,7 @@ int main(void)
|
||||
DEFINE(VCORE_TB_OFFSET, offsetof(struct kvmppc_vcore, tb_offset));
|
||||
DEFINE(VCORE_LPCR, offsetof(struct kvmppc_vcore, lpcr));
|
||||
DEFINE(VCORE_PCR, offsetof(struct kvmppc_vcore, pcr));
|
||||
DEFINE(VCORE_DPDES, offsetof(struct kvmppc_vcore, dpdes));
|
||||
DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
|
||||
DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv));
|
||||
DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb));
|
||||
|
@ -800,7 +800,7 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
|
||||
case KVM_REG_PPC_UAMOR:
|
||||
*val = get_reg_val(id, vcpu->arch.uamor);
|
||||
break;
|
||||
case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCRA:
|
||||
case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCRS:
|
||||
i = id - KVM_REG_PPC_MMCR0;
|
||||
*val = get_reg_val(id, vcpu->arch.mmcr[i]);
|
||||
break;
|
||||
@ -808,12 +808,85 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
|
||||
i = id - KVM_REG_PPC_PMC1;
|
||||
*val = get_reg_val(id, vcpu->arch.pmc[i]);
|
||||
break;
|
||||
case KVM_REG_PPC_SPMC1 ... KVM_REG_PPC_SPMC2:
|
||||
i = id - KVM_REG_PPC_SPMC1;
|
||||
*val = get_reg_val(id, vcpu->arch.spmc[i]);
|
||||
break;
|
||||
case KVM_REG_PPC_SIAR:
|
||||
*val = get_reg_val(id, vcpu->arch.siar);
|
||||
break;
|
||||
case KVM_REG_PPC_SDAR:
|
||||
*val = get_reg_val(id, vcpu->arch.sdar);
|
||||
break;
|
||||
case KVM_REG_PPC_SIER:
|
||||
*val = get_reg_val(id, vcpu->arch.sier);
|
||||
break;
|
||||
case KVM_REG_PPC_IAMR:
|
||||
*val = get_reg_val(id, vcpu->arch.iamr);
|
||||
break;
|
||||
case KVM_REG_PPC_TFHAR:
|
||||
*val = get_reg_val(id, vcpu->arch.tfhar);
|
||||
break;
|
||||
case KVM_REG_PPC_TFIAR:
|
||||
*val = get_reg_val(id, vcpu->arch.tfiar);
|
||||
break;
|
||||
case KVM_REG_PPC_TEXASR:
|
||||
*val = get_reg_val(id, vcpu->arch.texasr);
|
||||
break;
|
||||
case KVM_REG_PPC_FSCR:
|
||||
*val = get_reg_val(id, vcpu->arch.fscr);
|
||||
break;
|
||||
case KVM_REG_PPC_PSPB:
|
||||
*val = get_reg_val(id, vcpu->arch.pspb);
|
||||
break;
|
||||
case KVM_REG_PPC_EBBHR:
|
||||
*val = get_reg_val(id, vcpu->arch.ebbhr);
|
||||
break;
|
||||
case KVM_REG_PPC_EBBRR:
|
||||
*val = get_reg_val(id, vcpu->arch.ebbrr);
|
||||
break;
|
||||
case KVM_REG_PPC_BESCR:
|
||||
*val = get_reg_val(id, vcpu->arch.bescr);
|
||||
break;
|
||||
case KVM_REG_PPC_TAR:
|
||||
*val = get_reg_val(id, vcpu->arch.tar);
|
||||
break;
|
||||
case KVM_REG_PPC_DPDES:
|
||||
*val = get_reg_val(id, vcpu->arch.vcore->dpdes);
|
||||
break;
|
||||
case KVM_REG_PPC_DAWR:
|
||||
*val = get_reg_val(id, vcpu->arch.dawr);
|
||||
break;
|
||||
case KVM_REG_PPC_DAWRX:
|
||||
*val = get_reg_val(id, vcpu->arch.dawrx);
|
||||
break;
|
||||
case KVM_REG_PPC_CIABR:
|
||||
*val = get_reg_val(id, vcpu->arch.ciabr);
|
||||
break;
|
||||
case KVM_REG_PPC_IC:
|
||||
*val = get_reg_val(id, vcpu->arch.ic);
|
||||
break;
|
||||
case KVM_REG_PPC_VTB:
|
||||
*val = get_reg_val(id, vcpu->arch.vtb);
|
||||
break;
|
||||
case KVM_REG_PPC_CSIGR:
|
||||
*val = get_reg_val(id, vcpu->arch.csigr);
|
||||
break;
|
||||
case KVM_REG_PPC_TACR:
|
||||
*val = get_reg_val(id, vcpu->arch.tacr);
|
||||
break;
|
||||
case KVM_REG_PPC_TCSCR:
|
||||
*val = get_reg_val(id, vcpu->arch.tcscr);
|
||||
break;
|
||||
case KVM_REG_PPC_PID:
|
||||
*val = get_reg_val(id, vcpu->arch.pid);
|
||||
break;
|
||||
case KVM_REG_PPC_ACOP:
|
||||
*val = get_reg_val(id, vcpu->arch.acop);
|
||||
break;
|
||||
case KVM_REG_PPC_WORT:
|
||||
*val = get_reg_val(id, vcpu->arch.wort);
|
||||
break;
|
||||
case KVM_REG_PPC_VPA_ADDR:
|
||||
spin_lock(&vcpu->arch.vpa_update_lock);
|
||||
*val = get_reg_val(id, vcpu->arch.vpa.next_gpa);
|
||||
@ -882,7 +955,7 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
|
||||
case KVM_REG_PPC_UAMOR:
|
||||
vcpu->arch.uamor = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCRA:
|
||||
case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCRS:
|
||||
i = id - KVM_REG_PPC_MMCR0;
|
||||
vcpu->arch.mmcr[i] = set_reg_val(id, *val);
|
||||
break;
|
||||
@ -890,12 +963,88 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
|
||||
i = id - KVM_REG_PPC_PMC1;
|
||||
vcpu->arch.pmc[i] = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_SPMC1 ... KVM_REG_PPC_SPMC2:
|
||||
i = id - KVM_REG_PPC_SPMC1;
|
||||
vcpu->arch.spmc[i] = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_SIAR:
|
||||
vcpu->arch.siar = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_SDAR:
|
||||
vcpu->arch.sdar = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_SIER:
|
||||
vcpu->arch.sier = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_IAMR:
|
||||
vcpu->arch.iamr = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_TFHAR:
|
||||
vcpu->arch.tfhar = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_TFIAR:
|
||||
vcpu->arch.tfiar = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_TEXASR:
|
||||
vcpu->arch.texasr = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_FSCR:
|
||||
vcpu->arch.fscr = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_PSPB:
|
||||
vcpu->arch.pspb = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_EBBHR:
|
||||
vcpu->arch.ebbhr = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_EBBRR:
|
||||
vcpu->arch.ebbrr = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_BESCR:
|
||||
vcpu->arch.bescr = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_TAR:
|
||||
vcpu->arch.tar = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_DPDES:
|
||||
vcpu->arch.vcore->dpdes = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_DAWR:
|
||||
vcpu->arch.dawr = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_DAWRX:
|
||||
vcpu->arch.dawrx = set_reg_val(id, *val) & ~DAWRX_HYP;
|
||||
break;
|
||||
case KVM_REG_PPC_CIABR:
|
||||
vcpu->arch.ciabr = set_reg_val(id, *val);
|
||||
/* Don't allow setting breakpoints in hypervisor code */
|
||||
if ((vcpu->arch.ciabr & CIABR_PRIV) == CIABR_PRIV_HYPER)
|
||||
vcpu->arch.ciabr &= ~CIABR_PRIV; /* disable */
|
||||
break;
|
||||
case KVM_REG_PPC_IC:
|
||||
vcpu->arch.ic = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_VTB:
|
||||
vcpu->arch.vtb = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_CSIGR:
|
||||
vcpu->arch.csigr = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_TACR:
|
||||
vcpu->arch.tacr = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_TCSCR:
|
||||
vcpu->arch.tcscr = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_PID:
|
||||
vcpu->arch.pid = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_ACOP:
|
||||
vcpu->arch.acop = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_WORT:
|
||||
vcpu->arch.wort = set_reg_val(id, *val);
|
||||
break;
|
||||
case KVM_REG_PPC_VPA_ADDR:
|
||||
addr = set_reg_val(id, *val);
|
||||
r = -EINVAL;
|
||||
|
@ -460,6 +460,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
|
||||
beq 38f
|
||||
mtspr SPRN_PCR, r7
|
||||
38:
|
||||
|
||||
BEGIN_FTR_SECTION
|
||||
/* DPDES is shared between threads */
|
||||
ld r8, VCORE_DPDES(r5)
|
||||
mtspr SPRN_DPDES, r8
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
||||
|
||||
li r0,1
|
||||
stb r0,VCORE_IN_GUEST(r5) /* signal secondaries to continue */
|
||||
b 10f
|
||||
@ -659,6 +666,18 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
|
||||
mtspr SPRN_MMCRA, r6
|
||||
mtspr SPRN_SIAR, r7
|
||||
mtspr SPRN_SDAR, r8
|
||||
BEGIN_FTR_SECTION
|
||||
ld r5, VCPU_MMCR + 24(r4)
|
||||
ld r6, VCPU_SIER(r4)
|
||||
lwz r7, VCPU_PMC + 24(r4)
|
||||
lwz r8, VCPU_PMC + 28(r4)
|
||||
ld r9, VCPU_MMCR + 32(r4)
|
||||
mtspr SPRN_MMCR2, r5
|
||||
mtspr SPRN_SIER, r6
|
||||
mtspr SPRN_SPMC1, r7
|
||||
mtspr SPRN_SPMC2, r8
|
||||
mtspr SPRN_MMCRS, r9
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
||||
mtspr SPRN_MMCR0, r3
|
||||
isync
|
||||
|
||||
@ -690,6 +709,61 @@ BEGIN_FTR_SECTION
|
||||
mtspr SPRN_DSCR, r5
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
|
||||
|
||||
BEGIN_FTR_SECTION
|
||||
/* Skip next section on POWER7 or PPC970 */
|
||||
b 8f
|
||||
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
|
||||
/* Turn on TM so we can access TFHAR/TFIAR/TEXASR */
|
||||
mfmsr r8
|
||||
li r0, 1
|
||||
rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG
|
||||
mtmsrd r8
|
||||
|
||||
/* Load up POWER8-specific registers */
|
||||
ld r5, VCPU_IAMR(r4)
|
||||
lwz r6, VCPU_PSPB(r4)
|
||||
ld r7, VCPU_FSCR(r4)
|
||||
mtspr SPRN_IAMR, r5
|
||||
mtspr SPRN_PSPB, r6
|
||||
mtspr SPRN_FSCR, r7
|
||||
ld r5, VCPU_DAWR(r4)
|
||||
ld r6, VCPU_DAWRX(r4)
|
||||
ld r7, VCPU_CIABR(r4)
|
||||
ld r8, VCPU_TAR(r4)
|
||||
mtspr SPRN_DAWR, r5
|
||||
mtspr SPRN_DAWRX, r6
|
||||
mtspr SPRN_CIABR, r7
|
||||
mtspr SPRN_TAR, r8
|
||||
ld r5, VCPU_IC(r4)
|
||||
ld r6, VCPU_VTB(r4)
|
||||
mtspr SPRN_IC, r5
|
||||
mtspr SPRN_VTB, r6
|
||||
ld r5, VCPU_TFHAR(r4)
|
||||
ld r6, VCPU_TFIAR(r4)
|
||||
ld r7, VCPU_TEXASR(r4)
|
||||
ld r8, VCPU_EBBHR(r4)
|
||||
mtspr SPRN_TFHAR, r5
|
||||
mtspr SPRN_TFIAR, r6
|
||||
mtspr SPRN_TEXASR, r7
|
||||
mtspr SPRN_EBBHR, r8
|
||||
ld r5, VCPU_EBBRR(r4)
|
||||
ld r6, VCPU_BESCR(r4)
|
||||
ld r7, VCPU_CSIGR(r4)
|
||||
ld r8, VCPU_TACR(r4)
|
||||
mtspr SPRN_EBBRR, r5
|
||||
mtspr SPRN_BESCR, r6
|
||||
mtspr SPRN_CSIGR, r7
|
||||
mtspr SPRN_TACR, r8
|
||||
ld r5, VCPU_TCSCR(r4)
|
||||
ld r6, VCPU_ACOP(r4)
|
||||
lwz r7, VCPU_GUEST_PID(r4)
|
||||
ld r8, VCPU_WORT(r4)
|
||||
mtspr SPRN_TCSCR, r5
|
||||
mtspr SPRN_ACOP, r6
|
||||
mtspr SPRN_PID, r7
|
||||
mtspr SPRN_WORT, r8
|
||||
8:
|
||||
|
||||
/*
|
||||
* Set the decrementer to the guest decrementer.
|
||||
*/
|
||||
@ -1081,6 +1155,54 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_201)
|
||||
add r5,r5,r6
|
||||
std r5,VCPU_DEC_EXPIRES(r9)
|
||||
|
||||
BEGIN_FTR_SECTION
|
||||
b 8f
|
||||
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
|
||||
/* Turn on TM so we can access TFHAR/TFIAR/TEXASR */
|
||||
mfmsr r8
|
||||
li r0, 1
|
||||
rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG
|
||||
mtmsrd r8
|
||||
|
||||
/* Save POWER8-specific registers */
|
||||
mfspr r5, SPRN_IAMR
|
||||
mfspr r6, SPRN_PSPB
|
||||
mfspr r7, SPRN_FSCR
|
||||
std r5, VCPU_IAMR(r9)
|
||||
stw r6, VCPU_PSPB(r9)
|
||||
std r7, VCPU_FSCR(r9)
|
||||
mfspr r5, SPRN_IC
|
||||
mfspr r6, SPRN_VTB
|
||||
mfspr r7, SPRN_TAR
|
||||
std r5, VCPU_IC(r9)
|
||||
std r6, VCPU_VTB(r9)
|
||||
std r7, VCPU_TAR(r9)
|
||||
mfspr r5, SPRN_TFHAR
|
||||
mfspr r6, SPRN_TFIAR
|
||||
mfspr r7, SPRN_TEXASR
|
||||
mfspr r8, SPRN_EBBHR
|
||||
std r5, VCPU_TFHAR(r9)
|
||||
std r6, VCPU_TFIAR(r9)
|
||||
std r7, VCPU_TEXASR(r9)
|
||||
std r8, VCPU_EBBHR(r9)
|
||||
mfspr r5, SPRN_EBBRR
|
||||
mfspr r6, SPRN_BESCR
|
||||
mfspr r7, SPRN_CSIGR
|
||||
mfspr r8, SPRN_TACR
|
||||
std r5, VCPU_EBBRR(r9)
|
||||
std r6, VCPU_BESCR(r9)
|
||||
std r7, VCPU_CSIGR(r9)
|
||||
std r8, VCPU_TACR(r9)
|
||||
mfspr r5, SPRN_TCSCR
|
||||
mfspr r6, SPRN_ACOP
|
||||
mfspr r7, SPRN_PID
|
||||
mfspr r8, SPRN_WORT
|
||||
std r5, VCPU_TCSCR(r9)
|
||||
std r6, VCPU_ACOP(r9)
|
||||
stw r7, VCPU_GUEST_PID(r9)
|
||||
std r8, VCPU_WORT(r9)
|
||||
8:
|
||||
|
||||
/* Save and reset AMR and UAMOR before turning on the MMU */
|
||||
BEGIN_FTR_SECTION
|
||||
mfspr r5,SPRN_AMR
|
||||
@ -1190,6 +1312,20 @@ BEGIN_FTR_SECTION
|
||||
stw r10, VCPU_PMC + 24(r9)
|
||||
stw r11, VCPU_PMC + 28(r9)
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
|
||||
BEGIN_FTR_SECTION
|
||||
mfspr r4, SPRN_MMCR2
|
||||
mfspr r5, SPRN_SIER
|
||||
mfspr r6, SPRN_SPMC1
|
||||
mfspr r7, SPRN_SPMC2
|
||||
mfspr r8, SPRN_MMCRS
|
||||
std r4, VCPU_MMCR + 24(r9)
|
||||
std r5, VCPU_SIER(r9)
|
||||
stw r6, VCPU_PMC + 24(r9)
|
||||
stw r7, VCPU_PMC + 28(r9)
|
||||
std r8, VCPU_MMCR + 32(r9)
|
||||
lis r4, 0x8000
|
||||
mtspr SPRN_MMCRS, r4
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
||||
22:
|
||||
/* Clear out SLB */
|
||||
li r5,0
|
||||
@ -1290,6 +1426,15 @@ secondary_too_late:
|
||||
mtspr SPRN_LPID,r7
|
||||
isync
|
||||
|
||||
BEGIN_FTR_SECTION
|
||||
/* DPDES is shared between threads */
|
||||
mfspr r7, SPRN_DPDES
|
||||
std r7, VCORE_DPDES(r5)
|
||||
/* clear DPDES so we don't get guest doorbells in the host */
|
||||
li r8, 0
|
||||
mtspr SPRN_DPDES, r8
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
||||
|
||||
/* Subtract timebase offset from timebase */
|
||||
ld r8,VCORE_TB_OFFSET(r5)
|
||||
cmpdi r8,0
|
||||
|
Loading…
Reference in New Issue
Block a user