From 9a4fc4eaf111ca960c9f524b850598e9dbc9697f Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 10 Jul 2014 19:34:31 +1000 Subject: powerpc/kvm: Create proper names for the kvm_host_state PMU fields We have two arrays in kvm_host_state that contain register values for the PMU. Currently we only create an asm-offsets symbol for the base of the arrays, and do the array offset in the assembly code. Creating an asm-offsets symbol for each field individually makes the code much nicer to read, particularly for the MMCRx/SIxR/SDAR fields, and might have helped us notice the recent double restore bug we had in this code. Signed-off-by: Michael Ellerman Acked-by: Alexander Graf --- arch/powerpc/kernel/asm-offsets.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index e624f9646350..4717859fdd04 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -644,8 +644,19 @@ int main(void) HSTATE_FIELD(HSTATE_SAVED_XIRR, saved_xirr); HSTATE_FIELD(HSTATE_HOST_IPI, host_ipi); HSTATE_FIELD(HSTATE_PTID, ptid); - HSTATE_FIELD(HSTATE_MMCR, host_mmcr); - HSTATE_FIELD(HSTATE_PMC, host_pmc); + HSTATE_FIELD(HSTATE_MMCR0, host_mmcr[0]); + HSTATE_FIELD(HSTATE_MMCR1, host_mmcr[1]); + HSTATE_FIELD(HSTATE_MMCRA, host_mmcr[2]); + HSTATE_FIELD(HSTATE_SIAR, host_mmcr[3]); + HSTATE_FIELD(HSTATE_SDAR, host_mmcr[4]); + HSTATE_FIELD(HSTATE_MMCR2, host_mmcr[5]); + HSTATE_FIELD(HSTATE_SIER, host_mmcr[6]); + HSTATE_FIELD(HSTATE_PMC1, host_pmc[0]); + HSTATE_FIELD(HSTATE_PMC2, host_pmc[1]); + HSTATE_FIELD(HSTATE_PMC3, host_pmc[2]); + HSTATE_FIELD(HSTATE_PMC4, host_pmc[3]); + HSTATE_FIELD(HSTATE_PMC5, host_pmc[4]); + HSTATE_FIELD(HSTATE_PMC6, host_pmc[5]); HSTATE_FIELD(HSTATE_PURR, host_purr); HSTATE_FIELD(HSTATE_SPURR, host_spurr); HSTATE_FIELD(HSTATE_DSCR, host_dscr); -- cgit v1.2.3 From 145a2d0427a88e874f85e82e6fc42933a36f5a2b Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Mon, 15 Dec 2014 09:45:00 +0800 Subject: powerpc/pci: remove the multi-init for pci_dn->phb pci_dn->phb is set to phb in update_dn_pci_info(), if succeed. This patch removes the duplication of pci_dn->phb initialization. Signed-off-by: Wei Yang Reviewed-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/pci_dn.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 1f61fab59d9b..83df3075d3df 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -147,10 +147,8 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb) /* PHB nodes themselves must not match */ update_dn_pci_info(dn, phb); pdn = dn->data; - if (pdn) { + if (pdn) pdn->devfn = pdn->busno = -1; - pdn->phb = phb; - } /* Update dn->phb ptrs for new phb and children devices */ traverse_pci_devices(dn, update_dn_pci_info, phb); -- cgit v1.2.3 From 10ea834364c8670b3bf9bbbf6b9d27b4d2ebc9de Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 15 Jan 2015 12:01:42 +1100 Subject: powerpc: Rename _TIF_SYSCALL_T_OR_A to _TIF_SYSCALL_DOTRACE Once upon a time, at least 9 years ago (< 2.6.12), _TIF_SYSCALL_T_OR_A meant "TRACE or AUDIT". But these days it means TRACE or AUDIT or SECCOMP or TRACEPOINT or NOHZ. All of those are implemented via syscall_dotrace() so rename the flag to that to try and clarify things. Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/thread_info.h | 2 +- arch/powerpc/kernel/entry_32.S | 6 +++--- arch/powerpc/kernel/entry_64.S | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index ebc4f165690a..c1efa05613f0 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -124,7 +124,7 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_SYSCALL_TRACEPOINT (1< Date: Thu, 8 Jan 2015 16:40:51 +1100 Subject: powerpc/kernel: Avoid memory corruption at early stage When calling to early_setup(), we pick "boot_paca" up for the master CPU and initialize that with initialise_paca(). At that point, the SLB shadow buffer isn't populated yet. Updating the SLB shadow buffer should corrupt what we had in physical address 0 where the trap instruction is usually stored. This hasn't been observed to cause any trouble in practice, but is obviously fishy. Fixes: 6f4441ef7009 ("powerpc: Dynamically allocate slb_shadow from memblock") Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/paca.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index d6e195e8cd4c..5a23b69f8129 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c @@ -115,6 +115,14 @@ static struct slb_shadow * __init init_slb_shadow(int cpu) { struct slb_shadow *s = &slb_shadow[cpu]; + /* + * When we come through here to initialise boot_paca, the slb_shadow + * buffers are not allocated yet. That's OK, we'll get one later in + * boot, but make sure we don't corrupt memory at 0. + */ + if (!slb_shadow) + return NULL; + s->persistent = cpu_to_be32(SLB_NUM_BOLTED); s->buffer_length = cpu_to_be32(sizeof(*s)); -- cgit v1.2.3 From 2aa5cf9e48f2f39cc255f8e29964df3ff9ca017b Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 25 Nov 2014 09:27:00 +1100 Subject: powerpc/eeh: Fix missed PE#0 on P7IOC PE#0 should be regarded as valid for P7IOC, while it's invalid for PHB3. The patch adds flag EEH_VALID_PE_ZERO to differentiate those two cases. Without the patch, we possibly see frozen PE#0 state is cleared without EEH recovery taken on P7IOC as following kernel logs indicate: [root@ltcfbl8eb ~]# dmesg : pci 0000:00 : [PE# 000] Secondary bus 0 associated with PE#0 pci 0000:01 : [PE# 001] Secondary bus 1 associated with PE#1 pci 0001:00 : [PE# 000] Secondary bus 0 associated with PE#0 pci 0001:01 : [PE# 001] Secondary bus 1 associated with PE#1 pci 0002:00 : [PE# 000] Secondary bus 0 associated with PE#0 pci 0002:01 : [PE# 001] Secondary bus 1 associated with PE#1 pci 0003:00 : [PE# 000] Secondary bus 0 associated with PE#0 pci 0003:01 : [PE# 001] Secondary bus 1 associated with PE#1 pci 0003:20 : [PE# 002] Secondary bus 32..63 associated with PE#2 : EEH: Clear non-existing PHB#3-PE#0 EEH: PHB location: U78AE.001.WZS00M9-P1-002 Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/eeh.h | 5 +++-- arch/powerpc/kernel/eeh_pe.c | 14 +++++++++++--- arch/powerpc/platforms/powernv/eeh-powernv.c | 11 +++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 0652ebe117af..9c11d1ed6a36 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -38,8 +38,9 @@ struct device_node; #define EEH_FORCE_DISABLED 0x02 /* EEH disabled */ #define EEH_PROBE_MODE_DEV 0x04 /* From PCI device */ #define EEH_PROBE_MODE_DEVTREE 0x08 /* From device tree */ -#define EEH_ENABLE_IO_FOR_LOG 0x10 /* Enable IO for log */ -#define EEH_EARLY_DUMP_LOG 0x20 /* Dump log immediately */ +#define EEH_VALID_PE_ZERO 0x10 /* PE#0 is valid */ +#define EEH_ENABLE_IO_FOR_LOG 0x20 /* Enable IO for log */ +#define EEH_EARLY_DUMP_LOG 0x40 /* Dump log immediately */ /* * Delay for PE reset, all in ms diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index 5a63e2b0f65b..fa950fbc2d97 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c @@ -239,10 +239,18 @@ static void *__eeh_pe_get(void *data, void *flag) if (pe->type & EEH_PE_PHB) return NULL; - /* We prefer PE address */ - if (edev->pe_config_addr && - (edev->pe_config_addr == pe->addr)) + /* + * We prefer PE address. For most cases, we should + * have non-zero PE address + */ + if (eeh_has_flag(EEH_VALID_PE_ZERO)) { + if (edev->pe_config_addr == pe->addr) + return pe; + } else { + if (edev->pe_config_addr && + (edev->pe_config_addr == pe->addr)) return pe; + } /* Try BDF address */ if (edev->config_addr && diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 1d19e7917d7f..e261869adc86 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -68,6 +68,17 @@ static int powernv_eeh_init(void) if (phb->model == PNV_PHB_MODEL_P7IOC) eeh_add_flag(EEH_ENABLE_IO_FOR_LOG); + + /* + * PE#0 should be regarded as valid by EEH core + * if it's not the reserved one. Currently, we + * have the reserved PE#0 and PE#127 for PHB3 + * and P7IOC separately. So we should regard + * PE#0 as valid for P7IOC. + */ + if (phb->ioda.reserved_pe != 0) + eeh_add_flag(EEH_VALID_PE_ZERO); + break; } -- cgit v1.2.3 From 432227e9077eec13b3caf3aec6087f94a2f4327f Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Thu, 11 Dec 2014 14:28:55 +1100 Subject: powerpc/eeh: Introduce flag EEH_PE_REMOVED The conditions that one specific PE's frozen count exceeds the maximal allowed times (EEH_MAX_ALLOWED_FREEZES) and it's in isolated or recovery state indicate the PE was removed permanently implicitly. The patch introduces flag EEH_PE_REMOVED to indicate that explicitly so that we don't depend on the fixed maximal allowed times, which can be varied as we do in subsequent patch. Flag EEH_PE_REMOVED is expected to be marked for the PE whose frozen count exceeds the maximal allowed times, or just failed from recovery. Requested-by: Ryan Grimm Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/eeh.h | 1 + arch/powerpc/kernel/eeh_driver.c | 2 +- arch/powerpc/kernel/eeh_pe.c | 6 ++---- 3 files changed, 4 insertions(+), 5 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 9c11d1ed6a36..3e4dd34f2bd2 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -78,6 +78,7 @@ struct device_node; #define EEH_PE_KEEP (1 << 8) /* Keep PE on hotplug */ #define EEH_PE_CFG_RESTRICTED (1 << 9) /* Block config on error */ +#define EEH_PE_REMOVED (1 << 10) /* Removed permanently */ struct eeh_pe { int type; /* PE type: PHB/Bus/Device */ diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index b17e793ba67e..ac00672af7d1 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -806,7 +806,7 @@ perm_error: eeh_pe_dev_traverse(pe, eeh_report_failure, NULL); /* Mark the PE to be removed permanently */ - pe->freeze_count = EEH_MAX_ALLOWED_FREEZES + 1; + eeh_pe_state_mark(pe, EEH_PE_REMOVED); /* * Shut down the device drivers for good. We mark diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index fa950fbc2d97..1e4946c36f9e 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c @@ -526,8 +526,7 @@ static void *__eeh_pe_state_mark(void *data, void *flag) struct pci_dev *pdev; /* Keep the state of permanently removed PE intact */ - if ((pe->freeze_count > EEH_MAX_ALLOWED_FREEZES) && - (state & (EEH_PE_ISOLATED | EEH_PE_RECOVERING))) + if (pe->state & EEH_PE_REMOVED) return NULL; pe->state |= state; @@ -600,8 +599,7 @@ static void *__eeh_pe_state_clear(void *data, void *flag) struct pci_dev *pdev; /* Keep the state of permanently removed PE intact */ - if ((pe->freeze_count > EEH_MAX_ALLOWED_FREEZES) && - (state & EEH_PE_ISOLATED)) + if (pe->state & EEH_PE_REMOVED) return NULL; pe->state &= ~state; -- cgit v1.2.3 From 1b28f170d99170a1fdd22818a9610a73196b391d Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Thu, 11 Dec 2014 14:28:56 +1100 Subject: powerpc/eeh: Allow to set maximal frozen times When PE's frozen count hits maximal allowed frozen times, which is 5 currently, it will be forced to be offline permanently. Once the PE is removed permanently, rebooting machine is required to bring the PE back. It's not convienent when testing EEH functionality. The patch exports the maximal allowed frozen times through debugfs entry (/sys/kernel/debug/powerpc/eeh_max_freezes). Requested-by: Ryan Grimm Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/eeh.h | 7 +------ arch/powerpc/kernel/eeh.c | 24 ++++++++++++++++++++++++ arch/powerpc/kernel/eeh_driver.c | 2 +- 3 files changed, 26 insertions(+), 7 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 3e4dd34f2bd2..55abfd09e47f 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -218,6 +218,7 @@ struct eeh_ops { }; extern int eeh_subsystem_flags; +extern int eeh_max_freezes; extern struct eeh_ops *eeh_ops; extern raw_spinlock_t confirm_error_lock; @@ -255,12 +256,6 @@ static inline void eeh_serialize_unlock(unsigned long flags) raw_spin_unlock_irqrestore(&confirm_error_lock, flags); } -/* - * Max number of EEH freezes allowed before we consider the device - * to be permanently disabled. - */ -#define EEH_MAX_ALLOWED_FREEZES 5 - typedef void *(*eeh_traverse_func)(void *data, void *flag); void eeh_set_pe_aux_size(int size); int eeh_phb_pe_create(struct pci_controller *phb); diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index e1b6d8e17289..3b2252e7731b 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -104,6 +104,13 @@ int eeh_subsystem_flags; EXPORT_SYMBOL(eeh_subsystem_flags); +/* + * EEH allowed maximal frozen times. If one particular PE's + * frozen count in last hour exceeds this limit, the PE will + * be forced to be offline permanently. + */ +int eeh_max_freezes = 5; + /* Platform dependent EEH operations */ struct eeh_ops *eeh_ops = NULL; @@ -1652,8 +1659,22 @@ static int eeh_enable_dbgfs_get(void *data, u64 *val) return 0; } +static int eeh_freeze_dbgfs_set(void *data, u64 val) +{ + eeh_max_freezes = val; + return 0; +} + +static int eeh_freeze_dbgfs_get(void *data, u64 *val) +{ + *val = eeh_max_freezes; + return 0; +} + DEFINE_SIMPLE_ATTRIBUTE(eeh_enable_dbgfs_ops, eeh_enable_dbgfs_get, eeh_enable_dbgfs_set, "0x%llx\n"); +DEFINE_SIMPLE_ATTRIBUTE(eeh_freeze_dbgfs_ops, eeh_freeze_dbgfs_get, + eeh_freeze_dbgfs_set, "0x%llx\n"); #endif static int __init eeh_init_proc(void) @@ -1664,6 +1685,9 @@ static int __init eeh_init_proc(void) debugfs_create_file("eeh_enable", 0600, powerpc_debugfs_root, NULL, &eeh_enable_dbgfs_ops); + debugfs_create_file("eeh_max_freezes", 0600, + powerpc_debugfs_root, NULL, + &eeh_freeze_dbgfs_ops); #endif } diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index ac00672af7d1..d099540c0f56 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -667,7 +667,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) eeh_pe_update_time_stamp(pe); pe->freeze_count++; - if (pe->freeze_count > EEH_MAX_ALLOWED_FREEZES) + if (pe->freeze_count > eeh_max_freezes) goto excess_failures; pr_warn("EEH: This PCI device has failed %d times in the last hour\n", pe->freeze_count); -- cgit v1.2.3 From 3df76a9dcc74d5f012b94ea01ed6e7aaf8362c5a Mon Sep 17 00:00:00 2001 From: Cyril Bur Date: Wed, 21 Jan 2015 13:32:00 +1100 Subject: powerpc/pseries: Fix endian problems with LE migration RTAS events require arguments be passed in big endian while hypercalls have their arguments passed in registers and the values should therefore be in CPU endian. The "ibm,suspend_me" 'RTAS' call makes a sequence of hypercalls to setup one true RTAS call. This means that "ibm,suspend_me" is handled specially in the ppc_rtas() syscall. The ppc_rtas() syscall has its arguments in big endian and can therefore pass these arguments directly to the RTAS call. "ibm,suspend_me" is handled specially from within ppc_rtas() (by calling rtas_ibm_suspend_me()) which has left an endian bug on little endian systems due to the requirement of hypercalls. The return value from rtas_ibm_suspend_me() gets returned in cpu endian, and is left unconverted, also a bug on little endian systems. rtas_ibm_suspend_me() does not actually make use of the rtas_args that it is passed. This patch removes the convoluted use of the rtas_args struct to pass params to rtas_ibm_suspend_me() in favour of passing what it needs as actual arguments. This patch also ensures the two callers of rtas_ibm_suspend_me() pass function parameters in cpu endian and in the case of ppc_rtas(), converts the return value. migrate_store() (the other caller of rtas_ibm_suspend_me()) is from a sysfs file which deals with everything in cpu endian so this function only underwent cleanup. This patch has been tested with KVM both LE and BE and on PowerVM both LE and BE. Under QEMU/KVM the migration happens without touching these code pathes. For PowerVM there is no obvious regression on BE and the LE code path now provides the correct parameters to the hypervisor. Signed-off-by: Cyril Bur Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/rtas.h | 2 +- arch/powerpc/kernel/rtas.c | 22 +++++++++++++++------- arch/powerpc/platforms/pseries/mobility.c | 22 ++++++---------------- 3 files changed, 22 insertions(+), 24 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index b390f55b0df1..2e23e92a4372 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -327,7 +327,7 @@ extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data); extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data); extern int rtas_online_cpus_mask(cpumask_var_t cpus); extern int rtas_offline_cpus_mask(cpumask_var_t cpus); -extern int rtas_ibm_suspend_me(struct rtas_args *); +extern int rtas_ibm_suspend_me(u64 handle, int *vasi_return); struct rtc_time; extern unsigned long rtas_get_boot_time(void); diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4af905e81ab0..21c45a2d0706 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -897,7 +897,7 @@ int rtas_offline_cpus_mask(cpumask_var_t cpus) } EXPORT_SYMBOL(rtas_offline_cpus_mask); -int rtas_ibm_suspend_me(struct rtas_args *args) +int rtas_ibm_suspend_me(u64 handle, int *vasi_return) { long state; long rc; @@ -911,8 +911,7 @@ int rtas_ibm_suspend_me(struct rtas_args *args) return -ENOSYS; /* Make sure the state is valid */ - rc = plpar_hcall(H_VASI_STATE, retbuf, - ((u64)args->args[0] << 32) | args->args[1]); + rc = plpar_hcall(H_VASI_STATE, retbuf, handle); state = retbuf[0]; @@ -920,12 +919,12 @@ int rtas_ibm_suspend_me(struct rtas_args *args) printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc); return rc; } else if (state == H_VASI_ENABLED) { - args->args[args->nargs] = RTAS_NOT_SUSPENDABLE; + *vasi_return = RTAS_NOT_SUSPENDABLE; return 0; } else if (state != H_VASI_SUSPENDING) { printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n", state); - args->args[args->nargs] = -1; + *vasi_return = -1; return 0; } @@ -973,7 +972,7 @@ out: return atomic_read(&data.error); } #else /* CONFIG_PPC_PSERIES */ -int rtas_ibm_suspend_me(struct rtas_args *args) +int rtas_ibm_suspend_me(u64 handle, int *vasi_return) { return -ENOSYS; } @@ -1053,7 +1052,16 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) /* Need to handle ibm,suspend_me call specially */ if (token == ibm_suspend_me_token) { - rc = rtas_ibm_suspend_me(&args); + + /* + * rtas_ibm_suspend_me assumes args are in cpu endian, or at least the + * hcall within it requires it. + */ + int vasi_rc = 0; + u64 handle = ((u64)be32_to_cpu(args.args[0]) << 32) + | be32_to_cpu(args.args[1]); + rc = rtas_ibm_suspend_me(handle, &vasi_rc); + args.rets[0] = cpu_to_be32(vasi_rc); if (rc) return rc; goto copy_return; diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index e7cb6d4a871a..90cf3dcbd9f2 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c @@ -316,34 +316,24 @@ void post_mobility_fixup(void) static ssize_t migrate_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { - struct rtas_args args; u64 streamid; int rc; + int vasi_rc = 0; rc = kstrtou64(buf, 0, &streamid); if (rc) return rc; - memset(&args, 0, sizeof(args)); - args.token = rtas_token("ibm,suspend-me"); - args.nargs = 2; - args.nret = 1; - - args.args[0] = streamid >> 32 ; - args.args[1] = streamid & 0xffffffff; - args.rets = &args.args[args.nargs]; - do { - args.rets[0] = 0; - rc = rtas_ibm_suspend_me(&args); - if (!rc && args.rets[0] == RTAS_NOT_SUSPENDABLE) + rc = rtas_ibm_suspend_me(streamid, &vasi_rc); + if (!rc && vasi_rc == RTAS_NOT_SUSPENDABLE) ssleep(1); - } while (!rc && args.rets[0] == RTAS_NOT_SUSPENDABLE); + } while (!rc && vasi_rc == RTAS_NOT_SUSPENDABLE); if (rc) return rc; - else if (args.rets[0]) - return args.rets[0]; + if (vasi_rc) + return vasi_rc; post_mobility_fixup(); return count; -- cgit v1.2.3 From 8aa989b8fba1428b50a1be771c01285f1de0227b Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 27 Jan 2015 16:48:03 +1100 Subject: powerpc: Remove some unused functions Remove slice_set_psize() which is not used. It was added in 3a8247cc2c85 "powerpc: Only demote individual slices rather than whole process" but was never used. Remove vsx_assist_exception() which is not used. It was added in ce48b2100785 "powerpc: Add VSX context save/restore, ptrace and signal support" but was never used. Remove generic_mach_cpu_die() which is not used. Its last caller was removed in 375f561a4131 "powerpc/powernv: Always go into nap mode when CPU is offline". Remove mpc7448_hpc2_power_off() and mpc7448_hpc2_halt() which are unused. These were introduced in c5d56332fd6c "[POWERPC] Add general support for mpc7448hpc2 (Taiga) platform" but were never used. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist [mpe: Update changelog with details on when/why they are unused] Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/smp.h | 1 - arch/powerpc/kernel/smp.c | 14 ----------- arch/powerpc/kernel/traps.c | 15 ------------ arch/powerpc/mm/slice.c | 29 ----------------------- arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c | 11 --------- 5 files changed, 70 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index 5a6614a7f0b2..d607df5081a7 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -64,7 +64,6 @@ DECLARE_PER_CPU(unsigned int, cpu_pvr); extern void migrate_irqs(void); int generic_cpu_disable(void); void generic_cpu_die(unsigned int cpu); -void generic_mach_cpu_die(void); void generic_set_cpu_dead(unsigned int cpu); void generic_set_cpu_up(unsigned int cpu); int generic_check_cpu_restart(unsigned int cpu); diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 8ec017cb4446..1cc4bdce19f3 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -434,20 +434,6 @@ void generic_cpu_die(unsigned int cpu) printk(KERN_ERR "CPU%d didn't die...\n", cpu); } -void generic_mach_cpu_die(void) -{ - unsigned int cpu; - - local_irq_disable(); - idle_task_exit(); - cpu = smp_processor_id(); - printk(KERN_DEBUG "CPU%d offline\n", cpu); - __this_cpu_write(cpu_state, CPU_DEAD); - smp_wmb(); - while (__this_cpu_read(cpu_state) != CPU_UP_PREPARE) - cpu_relax(); -} - void generic_set_cpu_dead(unsigned int cpu) { per_cpu(cpu_state, cpu) = CPU_DEAD; diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index e6595b72269b..19e4744b6eba 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -1707,21 +1707,6 @@ void altivec_assist_exception(struct pt_regs *regs) } #endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_VSX -void vsx_assist_exception(struct pt_regs *regs) -{ - if (!user_mode(regs)) { - printk(KERN_EMERG "VSX assist exception in kernel mode" - " at %lx\n", regs->nip); - die("Kernel VSX assist exception", regs, SIGILL); - } - - flush_vsx_to_thread(current); - printk(KERN_INFO "VSX assist not supported at %lx\n", regs->nip); - _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); -} -#endif /* CONFIG_VSX */ - #ifdef CONFIG_FSL_BOOKE void CacheLockingException(struct pt_regs *regs, unsigned long address, unsigned long error_code) diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c index ded0ea1afde4..0f432a702870 100644 --- a/arch/powerpc/mm/slice.c +++ b/arch/powerpc/mm/slice.c @@ -645,35 +645,6 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize) spin_unlock_irqrestore(&slice_convert_lock, flags); } -void slice_set_psize(struct mm_struct *mm, unsigned long address, - unsigned int psize) -{ - unsigned char *hpsizes; - unsigned long i, flags; - u64 *lpsizes; - - spin_lock_irqsave(&slice_convert_lock, flags); - if (address < SLICE_LOW_TOP) { - i = GET_LOW_SLICE_INDEX(address); - lpsizes = &mm->context.low_slices_psize; - *lpsizes = (*lpsizes & ~(0xful << (i * 4))) | - ((unsigned long) psize << (i * 4)); - } else { - int index, mask_index; - i = GET_HIGH_SLICE_INDEX(address); - hpsizes = mm->context.high_slices_psize; - mask_index = i & 0x1; - index = i >> 1; - hpsizes[index] = (hpsizes[index] & - ~(0xf << (mask_index * 4))) | - (((unsigned long)psize) << (mask_index * 4)); - } - - spin_unlock_irqrestore(&slice_convert_lock, flags); - - copro_flush_all_slbs(mm); -} - void slice_set_range_psize(struct mm_struct *mm, unsigned long start, unsigned long len, unsigned int psize) { diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index beeaf4a173e1..df4ad95f183e 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -156,17 +156,6 @@ void mpc7448_hpc2_restart(char *cmd) for (;;) ; /* Spin until reset happens */ } -void mpc7448_hpc2_power_off(void) -{ - local_irq_disable(); - for (;;) ; /* No way to shut power off with software */ -} - -void mpc7448_hpc2_halt(void) -{ - mpc7448_hpc2_power_off(); -} - /* * Called very early, device-tree isn't unflattened */ -- cgit v1.2.3 From cadbfd01468663e8b9f9518a58ef67398a20d06b Mon Sep 17 00:00:00 2001 From: LEROY Christophe Date: Mon, 19 Jan 2015 17:04:44 +0100 Subject: powerpc/8xx: use _PAGE_RO instead of _PAGE_RW On powerpc 8xx, in TLB entries, 0x400 bit is set to 1 for read-only pages and is set to 0 for RW pages. So we should use _PAGE_RO instead of _PAGE_RW Signed-off-by: Christophe Leroy Signed-off-by: Scott Wood --- arch/powerpc/include/asm/pgtable-ppc32.h | 11 +++++------ arch/powerpc/include/asm/pte-8xx.h | 9 ++++----- arch/powerpc/kernel/head_8xx.S | 3 --- 3 files changed, 9 insertions(+), 14 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h index 62a3e49a9a14..9cde3c1522e3 100644 --- a/arch/powerpc/include/asm/pgtable-ppc32.h +++ b/arch/powerpc/include/asm/pgtable-ppc32.h @@ -178,12 +178,11 @@ static inline unsigned long pte_update(pte_t *p, andc %1,%0,%5\n\ or %1,%1,%6\n\ /* 0x200 == Extended encoding, bit 22 */ \ - /* Bit 22 has to be 1 if neither _PAGE_USER nor _PAGE_RW are set */ \ - rlwimi %1,%1,32-2,0x200\n /* get _PAGE_USER */ \ - rlwinm %3,%1,32-1,0x200\n /* get _PAGE_RW */ \ - or %1,%3,%1\n\ - xori %1,%1,0x200\n" -" stwcx. %1,0,%4\n\ + /* Bit 22 has to be 1 when _PAGE_USER is unset and _PAGE_RO is set */ \ + rlwimi %1,%1,32-1,0x200\n /* get _PAGE_RO */ \ + rlwinm %3,%1,32-2,0x200\n /* get _PAGE_USER */ \ + andc %1,%1,%3\n\ + stwcx. %1,0,%4\n\ bne- 1b" : "=&r" (old), "=&r" (tmp), "=m" (*p), "=&r" (tmp2) : "r" (p), "r" (clr), "r" (set), "m" (*p) diff --git a/arch/powerpc/include/asm/pte-8xx.h b/arch/powerpc/include/asm/pte-8xx.h index daa4616e61c4..eb6edb44f140 100644 --- a/arch/powerpc/include/asm/pte-8xx.h +++ b/arch/powerpc/include/asm/pte-8xx.h @@ -46,9 +46,9 @@ * require a TLB exception handler change. It is assumed unused bits * are always zero. */ -#define _PAGE_RW 0x0400 /* lsb PP bits, inverted in HW */ +#define _PAGE_RO 0x0400 /* lsb PP bits */ #define _PAGE_USER 0x0800 /* msb PP bits */ -/* set when neither _PAGE_USER nor _PAGE_RW are set */ +/* set when _PAGE_USER is unset and _PAGE_RO is set */ #define _PAGE_KNLRO 0x0200 #define _PMD_PRESENT 0x0001 @@ -62,9 +62,8 @@ #define PTE_ATOMIC_UPDATES 1 /* We need to add _PAGE_SHARED to kernel pages */ -#define _PAGE_KERNEL_RO (_PAGE_SHARED | _PAGE_KNLRO) -#define _PAGE_KERNEL_ROX (_PAGE_EXEC | _PAGE_KNLRO) -#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE) +#define _PAGE_KERNEL_RO (_PAGE_SHARED | _PAGE_RO | _PAGE_KNLRO) +#define _PAGE_KERNEL_ROX (_PAGE_EXEC | _PAGE_RO | _PAGE_KNLRO) #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_PTE_8xx_H */ diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index d99aac0d69f1..65492d043964 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -441,9 +441,6 @@ DataStoreTLBMiss: and r11, r11, r10 rlwimi r10, r11, 0, _PAGE_PRESENT #endif - /* invert RW */ - xori r10, r10, _PAGE_RW - /* The Linux PTE won't go exactly into the MMU TLB. * Software indicator bits 22 and 28 must be clear. * Software indicator bits 24, 25, 26, and 27 must be -- cgit v1.2.3 From 2374d0af29c154d6d989987a94278caed8c13be5 Mon Sep 17 00:00:00 2001 From: LEROY Christophe Date: Tue, 20 Jan 2015 10:57:33 +0100 Subject: powerpc/8xx: remove remaining unnecessary code in FixupDAR Since commit 33fb845a6f01 ("powerpc/8xx: Don't use MD_TWC for walk"), MD_EPN and MD_TWC are not writen anymore in FixupDAR so saving r3 has become useless. Signed-off-by: Christophe Leroy Signed-off-by: Scott Wood --- arch/powerpc/kernel/head_8xx.S | 6 ------ 1 file changed, 6 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 65492d043964..73715cd0de45 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -529,9 +529,6 @@ DARFixed:/* Return from dcbx instruction bug workaround */ /* define if you don't want to use self modifying code */ #define NO_SELF_MODIFYING_CODE FixupDAR:/* Entry point for dcbx workaround. */ -#ifdef CONFIG_8xx_CPU6 - mtspr SPRN_DAR, r3 -#endif mtspr SPRN_SPRG_SCRATCH2, r10 /* fetch instruction from memory. */ mfspr r10, SPRN_SRR0 @@ -548,9 +545,6 @@ FixupDAR:/* Entry point for dcbx workaround. */ /* Extract level 2 index */ rlwinm r11, r11, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 lwzx r11, r10, r11 /* Get the pte */ -#ifdef CONFIG_8xx_CPU6 - mfspr r3, SPRN_DAR -#endif /* concat physical page address(r11) and page offset(r10) */ mfspr r10, SPRN_SRR0 rlwimi r11, r10, 0, 32 - PAGE_SHIFT, 31 -- cgit v1.2.3 From 5ddb75cee5afab3bdaf6eb4efefc8029923a9cc7 Mon Sep 17 00:00:00 2001 From: LEROY Christophe Date: Tue, 20 Jan 2015 10:57:33 +0100 Subject: powerpc/8xx: remove tests on PGDIR entry validity Kernel MMU handling code handles validity of entries via _PMD_PRESENT which corresponds to V bit in MD_TWC and MI_TWC. When the V bit is not set, MPC8xx triggers TLBError exception. So we don't have to check that and branch ourself to TLBError. We can set TLB entries with non present entries, remove all those tests and let the 8xx handle it. This reduce the number of cycle when the entries are valid which is the case most of the time, and doesn't significantly increase the time for handling invalid entries. Signed-off-by: Christophe Leroy Signed-off-by: Scott Wood --- arch/powerpc/kernel/head_8xx.S | 41 ++++++++--------------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 73715cd0de45..32cc9e55b772 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -329,12 +329,9 @@ InstructionTLBMiss: /* Extract level 1 index */ rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 lwzx r11, r10, r11 /* Get the level 1 entry */ - rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ - beq 2f /* If zero, don't try to find a pte */ + rlwinm r10, r11,0,0,19 /* Extract page descriptor page address */ - /* We have a pte table, so load the MI_TWC with the attributes - * for this "segment." - */ + /* Load the MI_TWC with the attributes for this "segment." */ MTSPR_CPU6(SPRN_MI_TWC, r11, r3) /* Set segment attributes */ mfspr r11, SPRN_SRR0 /* Get effective address of fault */ /* Extract level 2 index */ @@ -342,13 +339,11 @@ InstructionTLBMiss: lwzx r10, r10, r11 /* Get the pte */ #ifdef CONFIG_SWAP - andi. r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT - cmpwi cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT - li r11, RPN_PATTERN - bne- cr0, 2f -#else - li r11, RPN_PATTERN + rlwinm r11, r10, 32-5, _PAGE_PRESENT + and r11, r11, r10 + rlwimi r10, r11, 0, _PAGE_PRESENT #endif + li r11, RPN_PATTERN /* The Linux PTE won't go exactly into the MMU TLB. * Software indicator bits 21 and 28 must be clear. * Software indicator bits 24, 25, 26, and 27 must be @@ -366,21 +361,6 @@ InstructionTLBMiss: mfspr r10, SPRN_SPRG_SCRATCH2 EXCEPTION_EPILOG_0 rfi -2: - mfspr r10, SPRN_SRR1 - /* clear all error bits as TLB Miss - * sets a few unconditionally - */ - rlwinm r10, r10, 0, 0xffff - mtspr SPRN_SRR1, r10 - - /* Restore registers */ -#ifdef CONFIG_8xx_CPU6 - mfspr r3, SPRN_DAR - mtspr SPRN_DAR, r11 /* Tag DAR */ -#endif - mfspr r10, SPRN_SPRG_SCRATCH2 - b InstructionTLBError1 . = 0x1200 DataStoreTLBMiss: @@ -403,8 +383,6 @@ DataStoreTLBMiss: /* Extract level 1 index */ rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 lwzx r11, r10, r11 /* Get the level 1 entry */ - rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ - beq 2f /* If zero, don't try to find a pte */ /* We have a pte table, so load fetch the pte from the table. */ @@ -447,7 +425,7 @@ DataStoreTLBMiss: * set. All other Linux PTE bits control the behavior * of the MMU. */ -2: li r11, RPN_PATTERN + li r11, RPN_PATTERN rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ MTSPR_CPU6(SPRN_MD_RPN, r10, r3) /* Update TLB entry */ @@ -466,10 +444,7 @@ DataStoreTLBMiss: */ . = 0x1300 InstructionTLBError: - EXCEPTION_PROLOG_0 -InstructionTLBError1: - EXCEPTION_PROLOG_1 - EXCEPTION_PROLOG_2 + EXCEPTION_PROLOG mr r4,r12 mr r5,r9 andis. r10,r5,0x4000 -- cgit v1.2.3 From 17bb312f4c75e59ef6f18015011c4efbb545a748 Mon Sep 17 00:00:00 2001 From: LEROY Christophe Date: Tue, 20 Jan 2015 10:57:34 +0100 Subject: powerpc/8xx: Take benefit of aligned PGDIR L1 base address is now aligned so we can insert L1 index into r11 directly and then preserve r10 Signed-off-by: Christophe Leroy Signed-off-by: Scott Wood --- arch/powerpc/kernel/head_8xx.S | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 32cc9e55b772..0ab16b66d712 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -326,16 +326,15 @@ InstructionTLBMiss: ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l 3: #endif - /* Extract level 1 index */ - rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 - lwzx r11, r10, r11 /* Get the level 1 entry */ - rlwinm r10, r11,0,0,19 /* Extract page descriptor page address */ + /* Insert level 1 index */ + rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 + lwz r11, 0(r11) /* Get the level 1 entry */ /* Load the MI_TWC with the attributes for this "segment." */ MTSPR_CPU6(SPRN_MI_TWC, r11, r3) /* Set segment attributes */ - mfspr r11, SPRN_SRR0 /* Get effective address of fault */ + rlwinm r11, r11,0,0,19 /* Extract page descriptor page address */ /* Extract level 2 index */ - rlwinm r11, r11, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 + rlwinm r10, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 lwzx r10, r10, r11 /* Get the pte */ #ifdef CONFIG_SWAP @@ -380,13 +379,12 @@ DataStoreTLBMiss: lis r11, (swapper_pg_dir-PAGE_OFFSET)@h ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l 3: - /* Extract level 1 index */ - rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 - lwzx r11, r10, r11 /* Get the level 1 entry */ + /* Insert level 1 index */ + rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 + lwz r11, 0(r11) /* Get the level 1 entry */ /* We have a pte table, so load fetch the pte from the table. */ - mfspr r10, SPRN_MD_EPN /* Get address of fault */ /* Extract level 2 index */ rlwinm r10, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 rlwimi r10, r11, 0, 0, 32 - PAGE_SHIFT - 1 /* Add level 2 base */ @@ -512,16 +510,14 @@ FixupDAR:/* Entry point for dcbx workaround. */ beq- 3f /* Branch if user space */ lis r11, (swapper_pg_dir-PAGE_OFFSET)@h ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l - /* Extract level 1 index */ -3: rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 - lwzx r11, r10, r11 /* Get the level 1 entry */ - rlwinm r10, r11,0,0,19 /* Extract page descriptor page address */ - mfspr r11, SPRN_SRR0 /* Get effective address of fault */ - /* Extract level 2 index */ - rlwinm r11, r11, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 - lwzx r11, r10, r11 /* Get the pte */ + /* Insert level 1 index */ +3: rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 + lwz r11, 0(r11) /* Get the level 1 entry */ + rlwinm r11, r11,0,0,19 /* Extract page descriptor page address */ + /* Insert level 2 index */ + rlwimi r11, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 + lwz r11, 0(r11) /* Get the pte */ /* concat physical page address(r11) and page offset(r10) */ - mfspr r10, SPRN_SRR0 rlwimi r11, r10, 0, 32 - PAGE_SHIFT, 31 lwz r11,0(r11) /* Check if it really is a dcbx instruction. */ -- cgit v1.2.3 From fde5a9057fcf2e96da1de3b6acf815c1e7d73f1e Mon Sep 17 00:00:00 2001 From: LEROY Christophe Date: Tue, 20 Jan 2015 10:57:34 +0100 Subject: powerpc/8xx: Optimise access to swapper_pg_dir All accessed to PGD entries are done via 0(r11). By using lower part of swapper_pg_dir as load index to r11, we can remove the ori instruction. Signed-off-by: Christophe Leroy Signed-off-by: Scott Wood --- arch/powerpc/kernel/head_8xx.S | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 0ab16b66d712..24934e79cd23 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -319,16 +319,15 @@ InstructionTLBMiss: * pin the first 8MB of kernel memory */ andis. r11, r10, 0x8000 /* Address >= 0x80000000 */ #endif - mfspr r11, SPRN_M_TW /* Get level 1 table base address */ + mfspr r11, SPRN_M_TW /* Get level 1 table */ #ifdef CONFIG_MODULES beq 3f - lis r11, (swapper_pg_dir-PAGE_OFFSET)@h - ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l + lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha 3: #endif /* Insert level 1 index */ rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 - lwz r11, 0(r11) /* Get the level 1 entry */ + lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11) /* Get the level 1 entry */ /* Load the MI_TWC with the attributes for this "segment." */ MTSPR_CPU6(SPRN_MI_TWC, r11, r3) /* Set segment attributes */ @@ -374,14 +373,13 @@ DataStoreTLBMiss: * kernel page tables. */ andis. r11, r10, 0x8000 - mfspr r11, SPRN_M_TW /* Get level 1 table base address */ + mfspr r11, SPRN_M_TW /* Get level 1 table */ beq 3f - lis r11, (swapper_pg_dir-PAGE_OFFSET)@h - ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l + lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha 3: /* Insert level 1 index */ rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 - lwz r11, 0(r11) /* Get the level 1 entry */ + lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11) /* Get the level 1 entry */ /* We have a pte table, so load fetch the pte from the table. */ @@ -506,13 +504,12 @@ FixupDAR:/* Entry point for dcbx workaround. */ /* fetch instruction from memory. */ mfspr r10, SPRN_SRR0 andis. r11, r10, 0x8000 /* Address >= 0x80000000 */ - mfspr r11, SPRN_M_TW /* Get level 1 table base address */ - beq- 3f /* Branch if user space */ - lis r11, (swapper_pg_dir-PAGE_OFFSET)@h - ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l + mfspr r11, SPRN_M_TW /* Get level 1 table */ + beq 3f + lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha /* Insert level 1 index */ 3: rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 - lwz r11, 0(r11) /* Get the level 1 entry */ + lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11) /* Get the level 1 entry */ rlwinm r11, r11,0,0,19 /* Extract page descriptor page address */ /* Insert level 2 index */ rlwimi r11, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 @@ -667,8 +664,7 @@ start_here: * init's THREAD like the context switch code does, but this is * easier......until someone changes init's static structures. */ - lis r6, swapper_pg_dir@h - ori r6, r6, swapper_pg_dir@l + lis r6, swapper_pg_dir@ha tophys(r6,r6) #ifdef CONFIG_8xx_CPU6 lis r4, cpu6_errata_word@h @@ -847,6 +843,13 @@ _GLOBAL(set_context) stw r4, 0x4(r5) #endif + /* Register M_TW will contain base address of level 1 table minus the + * lower part of the kernel PGDIR base address, so that all accesses to + * level 1 table are done relative to lower part of kernel PGDIR base + * address. + */ + li r5, (swapper_pg_dir-PAGE_OFFSET)@l + sub r4, r4, r5 #ifdef CONFIG_8xx_CPU6 lis r6, cpu6_errata_word@h ori r6, r6, cpu6_errata_word@l @@ -854,7 +857,7 @@ _GLOBAL(set_context) li r7, 0x3f80 stw r7, 12(r6) lwz r7, 12(r6) - mtspr SPRN_M_TW, r4 /* Update MMU base address */ + mtspr SPRN_M_TW, r4 /* Update pointeur to level 1 table */ li r7, 0x3380 stw r7, 12(r6) lwz r7, 12(r6) -- cgit v1.2.3 From 4545ff7ed841df77a239a22bffed4fc977a7d7bc Mon Sep 17 00:00:00 2001 From: LEROY Christophe Date: Tue, 20 Jan 2015 10:57:34 +0100 Subject: powerpc/8xx: Remove duplicated code in set_context() Signed-off-by: Christophe Leroy Signed-off-by: Scott Wood --- arch/powerpc/kernel/head_8xx.S | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 24934e79cd23..9b53fe139bf6 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -850,23 +850,21 @@ _GLOBAL(set_context) */ li r5, (swapper_pg_dir-PAGE_OFFSET)@l sub r4, r4, r5 + tophys (r4, r4) #ifdef CONFIG_8xx_CPU6 lis r6, cpu6_errata_word@h ori r6, r6, cpu6_errata_word@l - tophys (r4, r4) li r7, 0x3f80 stw r7, 12(r6) lwz r7, 12(r6) +#endif mtspr SPRN_M_TW, r4 /* Update pointeur to level 1 table */ +#ifdef CONFIG_8xx_CPU6 li r7, 0x3380 stw r7, 12(r6) lwz r7, 12(r6) - mtspr SPRN_M_CASID, r3 /* Update context */ -#else - mtspr SPRN_M_CASID,r3 /* Update context */ - tophys (r4, r4) - mtspr SPRN_M_TW, r4 /* and pgd */ #endif + mtspr SPRN_M_CASID, r3 /* Update context */ SYNC blr -- cgit v1.2.3 From 974ff4e2d71148655f0ea23096dbca4555d24dab Mon Sep 17 00:00:00 2001 From: Esben Haabendal Date: Tue, 6 Jan 2015 12:26:59 +0100 Subject: powerpc: Add machine_check cpu function for e300c3 cpus Signed-off-by: Esben Haabendal Signed-off-by: Scott Wood --- arch/powerpc/kernel/cputable.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 808405906336..f337666768a7 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -1133,6 +1133,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .cpu_setup = __setup_cpu_603, + .machine_check = machine_check_generic, .num_pmcs = 4, .oprofile_cpu_type = "ppc/e300", .oprofile_type = PPC_OPROFILE_FSL_EMB, -- cgit v1.2.3 From 4c3b21686111e0ac6018469dacbc5549f9915cf8 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 5 Dec 2014 21:16:59 +1100 Subject: powerpc/kernel: Make syscall_exit a local label Currently when we back trace something that is in a syscall we see something like this: [c000000000000000] [c000000000000000] SyS_read+0x6c/0x110 [c000000000000000] [c000000000000000] syscall_exit+0x0/0x98 Although it's entirely correct, seeing syscall_exit at the bottom can be confusing - we were exiting from a syscall and then called SyS_read() ? If we instead change syscall_exit to be a local label we get something more intuitive: [c0000001fa46fde0] [c00000000026719c] SyS_read+0x6c/0x110 [c0000001fa46fe30] [c000000000009264] system_call+0x38/0xd0 ie. we were handling a system call, and it was SyS_read(). Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/entry_64.S | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 3291ed148bdf..fefaa1485bd3 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -178,7 +178,7 @@ system_call: /* label this so stack traces look sane */ mtctr r12 bctrl /* Call handler */ -syscall_exit: +.Lsyscall_exit: std r3,RESULT(r1) #ifdef SHOW_SYSCALLS bl do_show_syscall_exit @@ -270,7 +270,7 @@ syscall_dotrace: syscall_enosys: li r3,-ENOSYS - b syscall_exit + b .Lsyscall_exit syscall_exit_work: #ifdef CONFIG_PPC_BOOK3S @@ -347,33 +347,33 @@ _GLOBAL(save_nvgprs) _GLOBAL(ppc_fork) bl save_nvgprs bl sys_fork - b syscall_exit + b .Lsyscall_exit _GLOBAL(ppc_vfork) bl save_nvgprs bl sys_vfork - b syscall_exit + b .Lsyscall_exit _GLOBAL(ppc_clone) bl save_nvgprs bl sys_clone - b syscall_exit + b .Lsyscall_exit _GLOBAL(ppc32_swapcontext) bl save_nvgprs bl compat_sys_swapcontext - b syscall_exit + b .Lsyscall_exit _GLOBAL(ppc64_swapcontext) bl save_nvgprs bl sys_swapcontext - b syscall_exit + b .Lsyscall_exit _GLOBAL(ret_from_fork) bl schedule_tail REST_NVGPRS(r1) li r3,0 - b syscall_exit + b .Lsyscall_exit _GLOBAL(ret_from_kernel_thread) bl schedule_tail @@ -385,7 +385,7 @@ _GLOBAL(ret_from_kernel_thread) #endif blrl li r3,0 - b syscall_exit + b .Lsyscall_exit /* * This routine switches between two different tasks. The process -- cgit v1.2.3 From a4bcbe6a41adcaa5e7f1830a7c1da8691d9d2b1d Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 14 Jan 2015 14:47:56 +1100 Subject: powerpc: Remove old compile time disabled syscall tracing code We have code to do syscall tracing which is disabled at compile time by default. It's not been touched since the dawn of time (ie. v2.6.12). There are now better ways to do syscall tracing, ie. using the raw_syscall, or syscall tracepoints. For the specific case of tracing syscalls at boot on a system that doesn't get to userspace, you can boot with: trace_event=syscalls tp_printk=on Which will trace syscalls from boot, and echo all output to the console. Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/entry_32.S | 77 ------------------------------------------ arch/powerpc/kernel/entry_64.S | 13 ------- arch/powerpc/kernel/syscalls.c | 14 -------- 3 files changed, 104 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index da6379550fd2..46fc0f4d8982 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -33,9 +33,6 @@ #include #include -#undef SHOW_SYSCALLS -#undef SHOW_SYSCALLS_TASK - /* * MSR_KERNEL is > 0x10000 on 4xx/Book-E since it include MSR_CE. */ @@ -307,9 +304,6 @@ _GLOBAL(DoSyscall) lwz r11,_CCR(r1) /* Clear SO bit in CR */ rlwinm r11,r11,0,4,2 stw r11,_CCR(r1) -#ifdef SHOW_SYSCALLS - bl do_show_syscall -#endif /* SHOW_SYSCALLS */ #ifdef CONFIG_TRACE_IRQFLAGS /* Return from syscalls can (and generally will) hard enable * interrupts. You aren't supposed to call a syscall with @@ -352,9 +346,6 @@ syscall_dotrace_cont: blrl /* Call handler */ .globl ret_from_syscall ret_from_syscall: -#ifdef SHOW_SYSCALLS - bl do_show_syscall_exit -#endif mr r6,r3 CURRENT_THREAD_INFO(r12, r1) /* disable interrupts so current_thread_info()->flags can't change */ @@ -523,74 +514,6 @@ syscall_exit_work: bl do_syscall_trace_leave b ret_from_except_full -#ifdef SHOW_SYSCALLS -do_show_syscall: -#ifdef SHOW_SYSCALLS_TASK - lis r11,show_syscalls_task@ha - lwz r11,show_syscalls_task@l(r11) - cmp 0,r2,r11 - bnelr -#endif - stw r31,GPR31(r1) - mflr r31 - lis r3,7f@ha - addi r3,r3,7f@l - lwz r4,GPR0(r1) - lwz r5,GPR3(r1) - lwz r6,GPR4(r1) - lwz r7,GPR5(r1) - lwz r8,GPR6(r1) - lwz r9,GPR7(r1) - bl printk - lis r3,77f@ha - addi r3,r3,77f@l - lwz r4,GPR8(r1) - mr r5,r2 - bl printk - lwz r0,GPR0(r1) - lwz r3,GPR3(r1) - lwz r4,GPR4(r1) - lwz r5,GPR5(r1) - lwz r6,GPR6(r1) - lwz r7,GPR7(r1) - lwz r8,GPR8(r1) - mtlr r31 - lwz r31,GPR31(r1) - blr - -do_show_syscall_exit: -#ifdef SHOW_SYSCALLS_TASK - lis r11,show_syscalls_task@ha - lwz r11,show_syscalls_task@l(r11) - cmp 0,r2,r11 - bnelr -#endif - stw r31,GPR31(r1) - mflr r31 - stw r3,RESULT(r1) /* Save result */ - mr r4,r3 - lis r3,79f@ha - addi r3,r3,79f@l - bl printk - lwz r3,RESULT(r1) - mtlr r31 - lwz r31,GPR31(r1) - blr - -7: .string "syscall %d(%x, %x, %x, %x, %x, " -77: .string "%x), current=%p\n" -79: .string " -> %x\n" - .align 2,0 - -#ifdef SHOW_SYSCALLS_TASK - .data - .globl show_syscalls_task -show_syscalls_task: - .long -1 - .text -#endif -#endif /* SHOW_SYSCALLS */ - /* * The fork/clone functions need to copy the full register set into * the child process. Therefore we need to save all the nonvolatile diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index fefaa1485bd3..d180caf2d6de 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -49,8 +49,6 @@ exception_marker: .section ".text" .align 7 -#undef SHOW_SYSCALLS - .globl system_call_common system_call_common: andi. r10,r12,MSR_PR @@ -142,13 +140,6 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) li r10,1 std r10,SOFTE(r1) -#ifdef SHOW_SYSCALLS - bl do_show_syscall - REST_GPR(0,r1) - REST_4GPRS(3,r1) - REST_2GPRS(7,r1) - addi r9,r1,STACK_FRAME_OVERHEAD -#endif CURRENT_THREAD_INFO(r11, r1) ld r10,TI_FLAGS(r11) andi. r11,r10,_TIF_SYSCALL_DOTRACE @@ -180,10 +171,6 @@ system_call: /* label this so stack traces look sane */ .Lsyscall_exit: std r3,RESULT(r1) -#ifdef SHOW_SYSCALLS - bl do_show_syscall_exit - ld r3,RESULT(r1) -#endif CURRENT_THREAD_INFO(r12, r1) ld r8,_MSR(r1) diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c index cd9be9aa016d..b2702e87db0d 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c @@ -121,17 +121,3 @@ long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low, return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low, (u64)len_high << 32 | len_low, advice); } - -void do_show_syscall(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, unsigned long r8, - struct pt_regs *regs) -{ - printk("syscall %ld(%lx, %lx, %lx, %lx, %lx, %lx) regs=%p current=%p" - " cpu=%d\n", regs->gpr[0], r3, r4, r5, r6, r7, r8, regs, - current, smp_processor_id()); -} - -void do_show_syscall_exit(unsigned long r3) -{ - printk(" -> %lx, current=%p cpu=%d\n", r3, current, smp_processor_id()); -} -- cgit v1.2.3 From fe12545e7650de5332b5522a62686fab8bafc733 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Thu, 8 Jan 2015 16:41:47 +1100 Subject: powerpc/kernel: Avoid initializing device-tree pointer twice As commit 50ba08f3 ("of/fdt: Don't clear initial_boot_params if fdt_check_header() fails") does, the device-tree pointer "initial_boot_params" is initialized by early_init_dt_verify(), which is called by early_init_devtree(). So we needn't explicitly initialize that again in early_init_devtree(). Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/prom.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 6a799b3cc6b4..b8e15c678960 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -652,9 +652,6 @@ void __init early_init_devtree(void *params) if (!early_init_dt_verify(params)) panic("BUG: Failed verifying flat device tree, bad version?"); - /* Setup flat device-tree pointer */ - initial_boot_params = params; - #ifdef CONFIG_PPC_RTAS /* Some machines might need RTAS info for debugging, grab it now. */ of_scan_flat_dt(early_init_dt_scan_rtas, NULL); -- cgit v1.2.3