Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 373127
b: refs/heads/master
c: 4619ac8
h: refs/heads/master
i:
  373125: 8c2e964
  373123: f131003
  373119: 5ff3cb2
v: v3
  • Loading branch information
Paul Mackerras authored and Alexander Graf committed Apr 26, 2013
1 parent a30258c commit 9cbba79
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 65 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e7d26f285b4be9466c9e393139e1c9cffe4cedfc
refs/heads/master: 4619ac88b72c43c622ef1eae3069de0e6f2cba9d
1 change: 1 addition & 0 deletions trunk/arch/powerpc/include/asm/reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@
#define LPCR_PECE1 0x00002000 /* decrementer can cause exit */
#define LPCR_PECE2 0x00001000 /* machine check etc can cause exit */
#define LPCR_MER 0x00000800 /* Mediated External Exception */
#define LPCR_MER_SH 11
#define LPCR_LPES 0x0000000c
#define LPCR_LPES0 0x00000008 /* LPAR Env selector 0 */
#define LPCR_LPES1 0x00000004 /* LPAR Env selector 1 */
Expand Down
5 changes: 4 additions & 1 deletion trunk/arch/powerpc/kvm/book3s_hv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1384,9 +1384,12 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
break;
vc->runner = vcpu;
n_ceded = 0;
list_for_each_entry(v, &vc->runnable_threads, arch.run_list)
list_for_each_entry(v, &vc->runnable_threads, arch.run_list) {
if (!v->arch.pending_exceptions)
n_ceded += v->arch.ceded;
else
v->arch.ceded = 0;
}
if (n_ceded == vc->n_runnable)
kvmppc_vcore_blocked(vc);
else
Expand Down
138 changes: 75 additions & 63 deletions trunk/arch/powerpc/kvm/book3s_hv_rmhandlers.S
Original file line number Diff line number Diff line change
Expand Up @@ -97,50 +97,51 @@ kvm_start_guest:
li r0,1
stb r0,PACA_NAPSTATELOST(r13)

/* get vcpu pointer, NULL if we have no vcpu to run */
ld r4,HSTATE_KVM_VCPU(r13)
cmpdi cr1,r4,0
/* were we napping due to cede? */
lbz r0,HSTATE_NAPPING(r13)
cmpwi r0,0
bne kvm_end_cede

/*
* We weren't napping due to cede, so this must be a secondary
* thread being woken up to run a guest, or being woken up due
* to a stray IPI. (Or due to some machine check or hypervisor
* maintenance interrupt while the core is in KVM.)
*/

/* Check the wake reason in SRR1 to see why we got here */
mfspr r3,SPRN_SRR1
rlwinm r3,r3,44-31,0x7 /* extract wake reason field */
cmpwi r3,4 /* was it an external interrupt? */
bne 27f

/*
* External interrupt - for now assume it is an IPI, since we
* should never get any other interrupts sent to offline threads.
* Only do this for secondary threads.
*/
beq cr1,25f
lwz r3,VCPU_PTID(r4)
cmpwi r3,0
beq 27f
25: ld r5,HSTATE_XICS_PHYS(r13)
li r0,0xff
li r6,XICS_MFRR
li r7,XICS_XIRR
bne 27f /* if not */
ld r5,HSTATE_XICS_PHYS(r13)
li r7,XICS_XIRR /* if it was an external interrupt, */
lwzcix r8,r5,r7 /* get and ack the interrupt */
sync
clrldi. r9,r8,40 /* get interrupt source ID. */
beq 27f /* none there? */
cmpwi r9,XICS_IPI
bne 26f
beq 28f /* none there? */
cmpwi r9,XICS_IPI /* was it an IPI? */
bne 29f
li r0,0xff
li r6,XICS_MFRR
stbcix r0,r5,r6 /* clear IPI */
26: stwcix r8,r5,r7 /* EOI the interrupt */
stwcix r8,r5,r7 /* EOI the interrupt */
sync /* order loading of vcpu after that */

27: /* XXX should handle hypervisor maintenance interrupts etc. here */

/* reload vcpu pointer after clearing the IPI */
/* get vcpu pointer, NULL if we have no vcpu to run */
ld r4,HSTATE_KVM_VCPU(r13)
cmpdi r4,0
/* if we have no vcpu to run, go back to sleep */
beq kvm_no_guest
b kvmppc_hv_entry

/* were we napping due to cede? */
lbz r0,HSTATE_NAPPING(r13)
cmpwi r0,0
bne kvm_end_cede
27: /* XXX should handle hypervisor maintenance interrupts etc. here */
b kvm_no_guest
28: /* SRR1 said external but ICP said nope?? */
b kvm_no_guest
29: /* External non-IPI interrupt to offline secondary thread? help?? */
stw r8,HSTATE_SAVED_XIRR(r13)
b kvm_no_guest

.global kvmppc_hv_entry
kvmppc_hv_entry:
Expand Down Expand Up @@ -483,20 +484,20 @@ toc_tlbie_lock:
mtctr r6
mtxer r7

ld r10, VCPU_PC(r4)
ld r11, VCPU_MSR(r4)
kvmppc_cede_reentry: /* r4 = vcpu, r13 = paca */
ld r6, VCPU_SRR0(r4)
ld r7, VCPU_SRR1(r4)
ld r10, VCPU_PC(r4)
ld r11, VCPU_MSR(r4) /* r11 = vcpu->arch.msr & ~MSR_HV */

/* r11 = vcpu->arch.msr & ~MSR_HV */
rldicl r11, r11, 63 - MSR_HV_LG, 1
rotldi r11, r11, 1 + MSR_HV_LG
ori r11, r11, MSR_ME

/* Check if we can deliver an external or decrementer interrupt now */
ld r0,VCPU_PENDING_EXC(r4)
li r8,(1 << BOOK3S_IRQPRIO_EXTERNAL)
oris r8,r8,(1 << BOOK3S_IRQPRIO_EXTERNAL_LEVEL)@h
lis r8,(1 << BOOK3S_IRQPRIO_EXTERNAL_LEVEL)@h
and r0,r0,r8
cmpdi cr1,r0,0
andi. r0,r11,MSR_EE
Expand Down Expand Up @@ -524,10 +525,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
/* Move SRR0 and SRR1 into the respective regs */
5: mtspr SPRN_SRR0, r6
mtspr SPRN_SRR1, r7
li r0,0
stb r0,VCPU_CEDED(r4) /* cancel cede */

fast_guest_return:
li r0,0
stb r0,VCPU_CEDED(r4) /* cancel cede */
mtspr SPRN_HSRR0,r10
mtspr SPRN_HSRR1,r11

Expand Down Expand Up @@ -686,6 +687,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
/* External interrupt, first check for host_ipi. If this is
* set, we know the host wants us out so let's do it now
*/
do_ext_interrupt:
lbz r0, HSTATE_HOST_IPI(r13)
cmpwi r0, 0
bne ext_interrupt_to_host
Expand All @@ -698,19 +700,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
lwzcix r3, r5, r7
rlwinm. r0, r3, 0, 0xffffff
sync
bne 1f
beq 3f /* if nothing pending in the ICP */

/* Nothing pending in the ICP, check for mediated interrupts
* and bounce it to the guest
*/
andi. r0, r11, MSR_EE
beq ext_interrupt_to_host /* shouldn't happen ?? */
mfspr r5, SPRN_LPCR
andi. r0, r5, LPCR_MER
bne bounce_ext_interrupt
b ext_interrupt_to_host /* shouldn't happen ?? */

1: /* We found something in the ICP...
/* We found something in the ICP...
*
* If it's not an IPI, stash it in the PACA and return to
* the host, we don't (yet) handle directing real external
Expand All @@ -735,16 +727,33 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
bne- 1f

/* Allright, looks like an IPI for the guest, we need to set MER */
mfspr r8,SPRN_LPCR
ori r8,r8,LPCR_MER
mtspr SPRN_LPCR,r8
3:
/* Check if any CPU is heading out to the host, if so head out too */
ld r5, HSTATE_KVM_VCORE(r13)
lwz r0, VCORE_ENTRY_EXIT(r5)
cmpwi r0, 0x100
bge ext_interrupt_to_host

/* See if there is a pending interrupt for the guest */
mfspr r8, SPRN_LPCR
ld r0, VCPU_PENDING_EXC(r9)
/* Insert EXTERNAL_LEVEL bit into LPCR at the MER bit position */
rldicl. r0, r0, 64 - BOOK3S_IRQPRIO_EXTERNAL_LEVEL, 63
rldimi r8, r0, LPCR_MER_SH, 63 - LPCR_MER_SH
beq 2f

/* And if the guest EE is set, we can deliver immediately, else
* we return to the guest with MER set
*/
andi. r0, r11, MSR_EE
bne bounce_ext_interrupt
mr r4, r9
beq 2f
mtspr SPRN_SRR0, r10
mtspr SPRN_SRR1, r11
li r10, BOOK3S_INTERRUPT_EXTERNAL
li r11, (MSR_ME << 1) | 1 /* synthesize MSR_SF | MSR_ME */
rotldi r11, r11, 63
2: mr r4, r9
mtspr SPRN_LPCR, r8
b fast_guest_return

/* We raced with the host, we need to resend that IPI, bummer */
Expand Down Expand Up @@ -1487,15 +1496,6 @@ ignore_hdec:
mr r4,r9
b fast_guest_return

bounce_ext_interrupt:
mr r4,r9
mtspr SPRN_SRR0,r10
mtspr SPRN_SRR1,r11
li r10,BOOK3S_INTERRUPT_EXTERNAL
li r11,(MSR_ME << 1) | 1 /* synthesize MSR_SF | MSR_ME */
rotldi r11,r11,63
b fast_guest_return

_GLOBAL(kvmppc_h_set_dabr)
std r4,VCPU_DABR(r3)
/* Work around P7 bug where DABR can get corrupted on mtspr */
Expand Down Expand Up @@ -1601,6 +1601,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
b .

kvm_end_cede:
/* get vcpu pointer */
ld r4, HSTATE_KVM_VCPU(r13)

/* Woken by external or decrementer interrupt */
ld r1, HSTATE_HOST_R1(r13)

Expand Down Expand Up @@ -1640,6 +1643,16 @@ kvm_end_cede:
li r0,0
stb r0,HSTATE_NAPPING(r13)

/* Check the wake reason in SRR1 to see why we got here */
mfspr r3, SPRN_SRR1
rlwinm r3, r3, 44-31, 0x7 /* extract wake reason field */
cmpwi r3, 4 /* was it an external interrupt? */
li r12, BOOK3S_INTERRUPT_EXTERNAL
mr r9, r4
ld r10, VCPU_PC(r9)
ld r11, VCPU_MSR(r9)
beq do_ext_interrupt /* if so */

/* see if any other thread is already exiting */
lwz r0,VCORE_ENTRY_EXIT(r5)
cmpwi r0,0x100
Expand All @@ -1659,8 +1672,7 @@ kvm_cede_prodded:

/* we've ceded but we want to give control to the host */
kvm_cede_exit:
li r3,H_TOO_HARD
blr
b hcall_real_fallback

/* Try to handle a machine check in real mode */
machine_check_realmode:
Expand Down

0 comments on commit 9cbba79

Please sign in to comment.