|
@@ -134,6 +134,40 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void kvmppc_booke_queue_exception(struct kvm_vcpu *vcpu, int exception)
|
|
|
|
+{
|
|
|
|
+ unsigned int priority = exception_priority[exception];
|
|
|
|
+ set_bit(priority, &vcpu->arch.pending_exceptions);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void kvmppc_booke_clear_exception(struct kvm_vcpu *vcpu, int exception)
|
|
|
|
+{
|
|
|
|
+ unsigned int priority = exception_priority[exception];
|
|
|
|
+ clear_bit(priority, &vcpu->arch.pending_exceptions);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void kvmppc_core_queue_program(struct kvm_vcpu *vcpu)
|
|
|
|
+{
|
|
|
|
+ kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu)
|
|
|
|
+{
|
|
|
|
+ kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_DECREMENTER);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu)
|
|
|
|
+{
|
|
|
|
+ unsigned int priority = exception_priority[BOOKE_INTERRUPT_DECREMENTER];
|
|
|
|
+ return test_bit(priority, &vcpu->arch.pending_exceptions);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
|
|
|
|
+ struct kvm_interrupt *irq)
|
|
|
|
+{
|
|
|
|
+ kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_EXTERNAL);
|
|
|
|
+}
|
|
|
|
+
|
|
/* Check if we are ready to deliver the interrupt */
|
|
/* Check if we are ready to deliver the interrupt */
|
|
static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
|
|
static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
|
|
{
|
|
{
|
|
@@ -168,7 +202,7 @@ static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
|
|
return r;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
|
|
-static void kvmppc_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
|
|
|
|
|
|
+static void kvmppc_booke_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
|
|
{
|
|
{
|
|
switch (interrupt) {
|
|
switch (interrupt) {
|
|
case BOOKE_INTERRUPT_DECREMENTER:
|
|
case BOOKE_INTERRUPT_DECREMENTER:
|
|
@@ -183,7 +217,7 @@ static void kvmppc_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
|
|
}
|
|
}
|
|
|
|
|
|
/* Check pending exceptions and deliver one, if possible. */
|
|
/* Check pending exceptions and deliver one, if possible. */
|
|
-void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu)
|
|
|
|
|
|
+void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
|
|
{
|
|
{
|
|
unsigned long *pending = &vcpu->arch.pending_exceptions;
|
|
unsigned long *pending = &vcpu->arch.pending_exceptions;
|
|
unsigned int exception;
|
|
unsigned int exception;
|
|
@@ -193,8 +227,8 @@ void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu)
|
|
while (priority <= BOOKE_MAX_INTERRUPT) {
|
|
while (priority <= BOOKE_MAX_INTERRUPT) {
|
|
exception = priority_exception[priority];
|
|
exception = priority_exception[priority];
|
|
if (kvmppc_can_deliver_interrupt(vcpu, exception)) {
|
|
if (kvmppc_can_deliver_interrupt(vcpu, exception)) {
|
|
- kvmppc_clear_exception(vcpu, exception);
|
|
|
|
- kvmppc_deliver_interrupt(vcpu, exception);
|
|
|
|
|
|
+ kvmppc_booke_clear_exception(vcpu, exception);
|
|
|
|
+ kvmppc_booke_deliver_interrupt(vcpu, exception);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -251,7 +285,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|
/* Program traps generated by user-level software must be handled
|
|
/* Program traps generated by user-level software must be handled
|
|
* by the guest kernel. */
|
|
* by the guest kernel. */
|
|
vcpu->arch.esr = vcpu->arch.fault_esr;
|
|
vcpu->arch.esr = vcpu->arch.fault_esr;
|
|
- kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM);
|
|
|
|
|
|
+ kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM);
|
|
r = RESUME_GUEST;
|
|
r = RESUME_GUEST;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -284,27 +318,27 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|
break;
|
|
break;
|
|
|
|
|
|
case BOOKE_INTERRUPT_FP_UNAVAIL:
|
|
case BOOKE_INTERRUPT_FP_UNAVAIL:
|
|
- kvmppc_queue_exception(vcpu, exit_nr);
|
|
|
|
|
|
+ kvmppc_booke_queue_exception(vcpu, exit_nr);
|
|
r = RESUME_GUEST;
|
|
r = RESUME_GUEST;
|
|
break;
|
|
break;
|
|
|
|
|
|
case BOOKE_INTERRUPT_DATA_STORAGE:
|
|
case BOOKE_INTERRUPT_DATA_STORAGE:
|
|
vcpu->arch.dear = vcpu->arch.fault_dear;
|
|
vcpu->arch.dear = vcpu->arch.fault_dear;
|
|
vcpu->arch.esr = vcpu->arch.fault_esr;
|
|
vcpu->arch.esr = vcpu->arch.fault_esr;
|
|
- kvmppc_queue_exception(vcpu, exit_nr);
|
|
|
|
|
|
+ kvmppc_booke_queue_exception(vcpu, exit_nr);
|
|
vcpu->stat.dsi_exits++;
|
|
vcpu->stat.dsi_exits++;
|
|
r = RESUME_GUEST;
|
|
r = RESUME_GUEST;
|
|
break;
|
|
break;
|
|
|
|
|
|
case BOOKE_INTERRUPT_INST_STORAGE:
|
|
case BOOKE_INTERRUPT_INST_STORAGE:
|
|
vcpu->arch.esr = vcpu->arch.fault_esr;
|
|
vcpu->arch.esr = vcpu->arch.fault_esr;
|
|
- kvmppc_queue_exception(vcpu, exit_nr);
|
|
|
|
|
|
+ kvmppc_booke_queue_exception(vcpu, exit_nr);
|
|
vcpu->stat.isi_exits++;
|
|
vcpu->stat.isi_exits++;
|
|
r = RESUME_GUEST;
|
|
r = RESUME_GUEST;
|
|
break;
|
|
break;
|
|
|
|
|
|
case BOOKE_INTERRUPT_SYSCALL:
|
|
case BOOKE_INTERRUPT_SYSCALL:
|
|
- kvmppc_queue_exception(vcpu, exit_nr);
|
|
|
|
|
|
+ kvmppc_booke_queue_exception(vcpu, exit_nr);
|
|
vcpu->stat.syscall_exits++;
|
|
vcpu->stat.syscall_exits++;
|
|
r = RESUME_GUEST;
|
|
r = RESUME_GUEST;
|
|
break;
|
|
break;
|
|
@@ -318,7 +352,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|
gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr);
|
|
gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr);
|
|
if (!gtlbe) {
|
|
if (!gtlbe) {
|
|
/* The guest didn't have a mapping for it. */
|
|
/* The guest didn't have a mapping for it. */
|
|
- kvmppc_queue_exception(vcpu, exit_nr);
|
|
|
|
|
|
+ kvmppc_booke_queue_exception(vcpu, exit_nr);
|
|
vcpu->arch.dear = vcpu->arch.fault_dear;
|
|
vcpu->arch.dear = vcpu->arch.fault_dear;
|
|
vcpu->arch.esr = vcpu->arch.fault_esr;
|
|
vcpu->arch.esr = vcpu->arch.fault_esr;
|
|
vcpu->stat.dtlb_real_miss_exits++;
|
|
vcpu->stat.dtlb_real_miss_exits++;
|
|
@@ -360,7 +394,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|
gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr);
|
|
gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr);
|
|
if (!gtlbe) {
|
|
if (!gtlbe) {
|
|
/* The guest didn't have a mapping for it. */
|
|
/* The guest didn't have a mapping for it. */
|
|
- kvmppc_queue_exception(vcpu, exit_nr);
|
|
|
|
|
|
+ kvmppc_booke_queue_exception(vcpu, exit_nr);
|
|
vcpu->stat.itlb_real_miss_exits++;
|
|
vcpu->stat.itlb_real_miss_exits++;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -380,8 +414,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|
gtlbe->word2);
|
|
gtlbe->word2);
|
|
} else {
|
|
} else {
|
|
/* Guest mapped and leaped at non-RAM! */
|
|
/* Guest mapped and leaped at non-RAM! */
|
|
- kvmppc_queue_exception(vcpu,
|
|
|
|
- BOOKE_INTERRUPT_MACHINE_CHECK);
|
|
|
|
|
|
+ kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_MACHINE_CHECK);
|
|
}
|
|
}
|
|
|
|
|
|
break;
|
|
break;
|
|
@@ -409,7 +442,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|
|
|
|
|
local_irq_disable();
|
|
local_irq_disable();
|
|
|
|
|
|
- kvmppc_check_and_deliver_interrupts(vcpu);
|
|
|
|
|
|
+ kvmppc_core_deliver_interrupts(vcpu);
|
|
|
|
|
|
/* Do some exit accounting. */
|
|
/* Do some exit accounting. */
|
|
vcpu->stat.sum_exits++;
|
|
vcpu->stat.sum_exits++;
|