forked from mirrors/linux
		
	KVM: PPC: Book3S HV: XIVE: Add a global reset control
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>
This commit is contained in:
		
							parent
							
								
									13ce3297c5
								
							
						
					
					
						commit
						5ca8064748
					
				
					 3 changed files with 91 additions and 0 deletions
				
			
		|  | @ -17,6 +17,11 @@ the legacy interrupt mode, referred as XICS (POWER7/8). | ||||||
| 
 | 
 | ||||||
|   1. KVM_DEV_XIVE_GRP_CTRL |   1. KVM_DEV_XIVE_GRP_CTRL | ||||||
|   Provides global controls on the device |   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) |   2. KVM_DEV_XIVE_GRP_SOURCE (write only) | ||||||
|   Initializes a new source in the XIVE device and mask it. |   Initializes a new source in the XIVE device and mask it. | ||||||
|  |  | ||||||
|  | @ -679,6 +679,7 @@ struct kvm_ppc_cpu_char { | ||||||
| 
 | 
 | ||||||
| /* POWER9 XIVE Native Interrupt Controller */ | /* POWER9 XIVE Native Interrupt Controller */ | ||||||
| #define KVM_DEV_XIVE_GRP_CTRL		1 | #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		2	/* 64-bit source identifier */ | ||||||
| #define KVM_DEV_XIVE_GRP_SOURCE_CONFIG	3	/* 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 */ | #define KVM_DEV_XIVE_GRP_EQ_CONFIG	4	/* 64-bit EQ identifier */ | ||||||
|  |  | ||||||
|  | @ -572,6 +572,83 @@ static int kvmppc_xive_native_get_queue_config(struct kvmppc_xive *xive, | ||||||
| 	return 0; | 	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, | static int kvmppc_xive_native_set_attr(struct kvm_device *dev, | ||||||
| 				       struct kvm_device_attr *attr) | 				       struct kvm_device_attr *attr) | ||||||
| { | { | ||||||
|  | @ -579,6 +656,10 @@ static int kvmppc_xive_native_set_attr(struct kvm_device *dev, | ||||||
| 
 | 
 | ||||||
| 	switch (attr->group) { | 	switch (attr->group) { | ||||||
| 	case KVM_DEV_XIVE_GRP_CTRL: | 	case KVM_DEV_XIVE_GRP_CTRL: | ||||||
|  | 		switch (attr->attr) { | ||||||
|  | 		case KVM_DEV_XIVE_RESET: | ||||||
|  | 			return kvmppc_xive_reset(xive); | ||||||
|  | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case KVM_DEV_XIVE_GRP_SOURCE: | 	case KVM_DEV_XIVE_GRP_SOURCE: | ||||||
| 		return kvmppc_xive_native_set_source(xive, attr->attr, | 		return kvmppc_xive_native_set_source(xive, attr->attr, | ||||||
|  | @ -611,6 +692,10 @@ static int kvmppc_xive_native_has_attr(struct kvm_device *dev, | ||||||
| { | { | ||||||
| 	switch (attr->group) { | 	switch (attr->group) { | ||||||
| 	case KVM_DEV_XIVE_GRP_CTRL: | 	case KVM_DEV_XIVE_GRP_CTRL: | ||||||
|  | 		switch (attr->attr) { | ||||||
|  | 		case KVM_DEV_XIVE_RESET: | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case KVM_DEV_XIVE_GRP_SOURCE: | 	case KVM_DEV_XIVE_GRP_SOURCE: | ||||||
| 	case KVM_DEV_XIVE_GRP_SOURCE_CONFIG: | 	case KVM_DEV_XIVE_GRP_SOURCE_CONFIG: | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Cédric Le Goater
						Cédric Le Goater