Skip to content

Commit

Permalink
KVM: PPC: Book3S HV: XIVE: Add a global reset control
Browse files Browse the repository at this point in the history
This control is to be used by the H_INT_RESET hcall from QEMU. Its
purpose is to clear all configuration of the sources and EQs. This is
necessary in case of a kexec (for a kdump kernel for instance) to make
sure that no remaining configuration is left from the previous boot
setup so that the new kernel can start safely from a clean state.

The queue 7 is ignored when the XIVE device is configured to run in
single escalation mode. Prio 7 is used by escalations.

The XIVE VP is kept enabled as the vCPU is still active and connected
to the XIVE device.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
  • Loading branch information
Cédric Le Goater authored and Paul Mackerras committed Apr 30, 2019
1 parent 13ce329 commit 5ca8064
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Documentation/virtual/kvm/devices/xive.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ the legacy interrupt mode, referred as XICS (POWER7/8).

1. KVM_DEV_XIVE_GRP_CTRL
Provides global controls on the device
Attributes:
1.1 KVM_DEV_XIVE_RESET (write only)
Resets the interrupt controller configuration for sources and event
queues. To be used by kexec and kdump.
Errors: none

2. KVM_DEV_XIVE_GRP_SOURCE (write only)
Initializes a new source in the XIVE device and mask it.
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/include/uapi/asm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ struct kvm_ppc_cpu_char {

/* POWER9 XIVE Native Interrupt Controller */
#define KVM_DEV_XIVE_GRP_CTRL 1
#define KVM_DEV_XIVE_RESET 1
#define KVM_DEV_XIVE_GRP_SOURCE 2 /* 64-bit source identifier */
#define KVM_DEV_XIVE_GRP_SOURCE_CONFIG 3 /* 64-bit source identifier */
#define KVM_DEV_XIVE_GRP_EQ_CONFIG 4 /* 64-bit EQ identifier */
Expand Down
85 changes: 85 additions & 0 deletions arch/powerpc/kvm/book3s_xive_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,13 +572,94 @@ static int kvmppc_xive_native_get_queue_config(struct kvmppc_xive *xive,
return 0;
}

static void kvmppc_xive_reset_sources(struct kvmppc_xive_src_block *sb)
{
int i;

for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) {
struct kvmppc_xive_irq_state *state = &sb->irq_state[i];

if (!state->valid)
continue;

if (state->act_priority == MASKED)
continue;

state->eisn = 0;
state->act_server = 0;
state->act_priority = MASKED;
xive_vm_esb_load(&state->ipi_data, XIVE_ESB_SET_PQ_01);
xive_native_configure_irq(state->ipi_number, 0, MASKED, 0);
if (state->pt_number) {
xive_vm_esb_load(state->pt_data, XIVE_ESB_SET_PQ_01);
xive_native_configure_irq(state->pt_number,
0, MASKED, 0);
}
}
}

static int kvmppc_xive_reset(struct kvmppc_xive *xive)
{
struct kvm *kvm = xive->kvm;
struct kvm_vcpu *vcpu;
unsigned int i;

pr_devel("%s\n", __func__);

mutex_lock(&kvm->lock);

kvm_for_each_vcpu(i, vcpu, kvm) {
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
unsigned int prio;

if (!xc)
continue;

kvmppc_xive_disable_vcpu_interrupts(vcpu);

for (prio = 0; prio < KVMPPC_XIVE_Q_COUNT; prio++) {

/* Single escalation, no queue 7 */
if (prio == 7 && xive->single_escalation)
break;

if (xc->esc_virq[prio]) {
free_irq(xc->esc_virq[prio], vcpu);
irq_dispose_mapping(xc->esc_virq[prio]);
kfree(xc->esc_virq_names[prio]);
xc->esc_virq[prio] = 0;
}

kvmppc_xive_native_cleanup_queue(vcpu, prio);
}
}

for (i = 0; i <= xive->max_sbid; i++) {
struct kvmppc_xive_src_block *sb = xive->src_blocks[i];

if (sb) {
arch_spin_lock(&sb->lock);
kvmppc_xive_reset_sources(sb);
arch_spin_unlock(&sb->lock);
}
}

mutex_unlock(&kvm->lock);

return 0;
}

static int kvmppc_xive_native_set_attr(struct kvm_device *dev,
struct kvm_device_attr *attr)
{
struct kvmppc_xive *xive = dev->private;

switch (attr->group) {
case KVM_DEV_XIVE_GRP_CTRL:
switch (attr->attr) {
case KVM_DEV_XIVE_RESET:
return kvmppc_xive_reset(xive);
}
break;
case KVM_DEV_XIVE_GRP_SOURCE:
return kvmppc_xive_native_set_source(xive, attr->attr,
Expand Down Expand Up @@ -611,6 +692,10 @@ static int kvmppc_xive_native_has_attr(struct kvm_device *dev,
{
switch (attr->group) {
case KVM_DEV_XIVE_GRP_CTRL:
switch (attr->attr) {
case KVM_DEV_XIVE_RESET:
return 0;
}
break;
case KVM_DEV_XIVE_GRP_SOURCE:
case KVM_DEV_XIVE_GRP_SOURCE_CONFIG:
Expand Down

0 comments on commit 5ca8064

Please sign in to comment.