Commit ab0a97cf authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'powerpc-6.8-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc fixes from Michael Ellerman:

 - Fix a crash when hot adding a PCI device to an LPAR since
   recent changes

 - Fix nested KVM level-2 guest reboot failure due to empty
   'arch_compat'

Thanks to Amit Machhiwal, Aneesh Kumar K.V (IBM), Brian King, Gaurav
Batra, and Vaibhav Jain.

* tag 'powerpc-6.8-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  KVM: PPC: Book3S HV: Fix L2 guest reboot failure due to empty 'arch_compat'
  powerpc/pseries/iommu: DLPAR add doesn't completely initialize pci_controller
parents 91403d50 20c8c4da
...@@ -30,6 +30,16 @@ void *pci_traverse_device_nodes(struct device_node *start, ...@@ -30,6 +30,16 @@ void *pci_traverse_device_nodes(struct device_node *start,
void *data); void *data);
extern void pci_devs_phb_init_dynamic(struct pci_controller *phb); extern void pci_devs_phb_init_dynamic(struct pci_controller *phb);
#if defined(CONFIG_IOMMU_API) && (defined(CONFIG_PPC_PSERIES) || \
defined(CONFIG_PPC_POWERNV))
extern void ppc_iommu_register_device(struct pci_controller *phb);
extern void ppc_iommu_unregister_device(struct pci_controller *phb);
#else
static inline void ppc_iommu_register_device(struct pci_controller *phb) { }
static inline void ppc_iommu_unregister_device(struct pci_controller *phb) { }
#endif
/* From rtas_pci.h */ /* From rtas_pci.h */
extern void init_pci_config_tokens (void); extern void init_pci_config_tokens (void);
extern unsigned long get_phb_buid (struct device_node *); extern unsigned long get_phb_buid (struct device_node *);
......
...@@ -1360,7 +1360,7 @@ static struct iommu_device *spapr_tce_iommu_probe_device(struct device *dev) ...@@ -1360,7 +1360,7 @@ static struct iommu_device *spapr_tce_iommu_probe_device(struct device *dev)
struct pci_controller *hose; struct pci_controller *hose;
if (!dev_is_pci(dev)) if (!dev_is_pci(dev))
return ERR_PTR(-EPERM); return ERR_PTR(-ENODEV);
pdev = to_pci_dev(dev); pdev = to_pci_dev(dev);
hose = pdev->bus->sysdata; hose = pdev->bus->sysdata;
...@@ -1409,6 +1409,21 @@ static const struct attribute_group *spapr_tce_iommu_groups[] = { ...@@ -1409,6 +1409,21 @@ static const struct attribute_group *spapr_tce_iommu_groups[] = {
NULL, NULL,
}; };
void ppc_iommu_register_device(struct pci_controller *phb)
{
iommu_device_sysfs_add(&phb->iommu, phb->parent,
spapr_tce_iommu_groups, "iommu-phb%04x",
phb->global_number);
iommu_device_register(&phb->iommu, &spapr_tce_iommu_ops,
phb->parent);
}
void ppc_iommu_unregister_device(struct pci_controller *phb)
{
iommu_device_unregister(&phb->iommu);
iommu_device_sysfs_remove(&phb->iommu);
}
/* /*
* This registers IOMMU devices of PHBs. This needs to happen * This registers IOMMU devices of PHBs. This needs to happen
* after core_initcall(iommu_init) + postcore_initcall(pci_driver_init) and * after core_initcall(iommu_init) + postcore_initcall(pci_driver_init) and
...@@ -1419,11 +1434,7 @@ static int __init spapr_tce_setup_phb_iommus_initcall(void) ...@@ -1419,11 +1434,7 @@ static int __init spapr_tce_setup_phb_iommus_initcall(void)
struct pci_controller *hose; struct pci_controller *hose;
list_for_each_entry(hose, &hose_list, list_node) { list_for_each_entry(hose, &hose_list, list_node) {
iommu_device_sysfs_add(&hose->iommu, hose->parent, ppc_iommu_register_device(hose);
spapr_tce_iommu_groups, "iommu-phb%04x",
hose->global_number);
iommu_device_register(&hose->iommu, &spapr_tce_iommu_ops,
hose->parent);
} }
return 0; return 0;
} }
......
...@@ -391,6 +391,24 @@ static void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 pvr) ...@@ -391,6 +391,24 @@ static void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 pvr)
/* Dummy value used in computing PCR value below */ /* Dummy value used in computing PCR value below */
#define PCR_ARCH_31 (PCR_ARCH_300 << 1) #define PCR_ARCH_31 (PCR_ARCH_300 << 1)
static inline unsigned long map_pcr_to_cap(unsigned long pcr)
{
unsigned long cap = 0;
switch (pcr) {
case PCR_ARCH_300:
cap = H_GUEST_CAP_POWER9;
break;
case PCR_ARCH_31:
cap = H_GUEST_CAP_POWER10;
break;
default:
break;
}
return cap;
}
static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
{ {
unsigned long host_pcr_bit = 0, guest_pcr_bit = 0, cap = 0; unsigned long host_pcr_bit = 0, guest_pcr_bit = 0, cap = 0;
...@@ -424,11 +442,9 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) ...@@ -424,11 +442,9 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
break; break;
case PVR_ARCH_300: case PVR_ARCH_300:
guest_pcr_bit = PCR_ARCH_300; guest_pcr_bit = PCR_ARCH_300;
cap = H_GUEST_CAP_POWER9;
break; break;
case PVR_ARCH_31: case PVR_ARCH_31:
guest_pcr_bit = PCR_ARCH_31; guest_pcr_bit = PCR_ARCH_31;
cap = H_GUEST_CAP_POWER10;
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -440,6 +456,12 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) ...@@ -440,6 +456,12 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
return -EINVAL; return -EINVAL;
if (kvmhv_on_pseries() && kvmhv_is_nestedv2()) { if (kvmhv_on_pseries() && kvmhv_is_nestedv2()) {
/*
* 'arch_compat == 0' would mean the guest should default to
* L1's compatibility. In this case, the guest would pick
* host's PCR and evaluate the corresponding capabilities.
*/
cap = map_pcr_to_cap(guest_pcr_bit);
if (!(cap & nested_capabilities)) if (!(cap & nested_capabilities))
return -EINVAL; return -EINVAL;
} }
......
...@@ -138,6 +138,7 @@ static int gs_msg_ops_vcpu_fill_info(struct kvmppc_gs_buff *gsb, ...@@ -138,6 +138,7 @@ static int gs_msg_ops_vcpu_fill_info(struct kvmppc_gs_buff *gsb,
vector128 v; vector128 v;
int rc, i; int rc, i;
u16 iden; u16 iden;
u32 arch_compat = 0;
vcpu = gsm->data; vcpu = gsm->data;
...@@ -347,8 +348,23 @@ static int gs_msg_ops_vcpu_fill_info(struct kvmppc_gs_buff *gsb, ...@@ -347,8 +348,23 @@ static int gs_msg_ops_vcpu_fill_info(struct kvmppc_gs_buff *gsb,
break; break;
} }
case KVMPPC_GSID_LOGICAL_PVR: case KVMPPC_GSID_LOGICAL_PVR:
rc = kvmppc_gse_put_u32(gsb, iden, /*
vcpu->arch.vcore->arch_compat); * Though 'arch_compat == 0' would mean the default
* compatibility, arch_compat, being a Guest Wide
* Element, cannot be filled with a value of 0 in GSB
* as this would result into a kernel trap.
* Hence, when `arch_compat == 0`, arch_compat should
* default to L1's PVR.
*/
if (!vcpu->arch.vcore->arch_compat) {
if (cpu_has_feature(CPU_FTR_ARCH_31))
arch_compat = PVR_ARCH_31;
else if (cpu_has_feature(CPU_FTR_ARCH_300))
arch_compat = PVR_ARCH_300;
} else {
arch_compat = vcpu->arch.vcore->arch_compat;
}
rc = kvmppc_gse_put_u32(gsb, iden, arch_compat);
break; break;
} }
......
...@@ -35,6 +35,8 @@ struct pci_controller *init_phb_dynamic(struct device_node *dn) ...@@ -35,6 +35,8 @@ struct pci_controller *init_phb_dynamic(struct device_node *dn)
pseries_msi_allocate_domains(phb); pseries_msi_allocate_domains(phb);
ppc_iommu_register_device(phb);
/* Create EEH devices for the PHB */ /* Create EEH devices for the PHB */
eeh_phb_pe_create(phb); eeh_phb_pe_create(phb);
...@@ -76,6 +78,8 @@ int remove_phb_dynamic(struct pci_controller *phb) ...@@ -76,6 +78,8 @@ int remove_phb_dynamic(struct pci_controller *phb)
} }
} }
ppc_iommu_unregister_device(phb);
pseries_msi_free_domains(phb); pseries_msi_free_domains(phb);
/* Keep a reference so phb isn't freed yet */ /* Keep a reference so phb isn't freed yet */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment