summaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/cacheinfo.c3
-rw-r--r--arch/powerpc/kernel/cpu_setup_power.c43
-rw-r--r--arch/powerpc/kernel/cpu_specs_book3s_64.h36
-rw-r--r--arch/powerpc/kernel/dt_cpu_ftrs.c44
-rw-r--r--arch/powerpc/kernel/eeh_driver.c2
-rw-r--r--arch/powerpc/kernel/head_64.S20
-rw-r--r--arch/powerpc/kernel/interrupt.c2
-rw-r--r--arch/powerpc/kernel/iommu.c2
-rw-r--r--arch/powerpc/kernel/irq.c16
-rw-r--r--arch/powerpc/kernel/pci-common.c9
-rw-r--r--arch/powerpc/kernel/prom.c1
-rw-r--r--arch/powerpc/kernel/prom_init.c46
-rw-r--r--arch/powerpc/kernel/rtas_flash.c27
-rw-r--r--arch/powerpc/kernel/rtas_pci.c8
-rw-r--r--arch/powerpc/kernel/rtasd.c19
-rw-r--r--arch/powerpc/kernel/setup-common.c1
-rw-r--r--arch/powerpc/kernel/smp.c3
-rw-r--r--arch/powerpc/kernel/syscall.c10
-rw-r--r--arch/powerpc/kernel/syscalls/syscall.tbl1
-rw-r--r--arch/powerpc/kernel/vdso/gettimeofday.S8
-rw-r--r--arch/powerpc/kernel/vdso/vdso32.lds.S8
-rw-r--r--arch/powerpc/kernel/vdso/vgettimeofday.c16
22 files changed, 246 insertions, 79 deletions
diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c
index 04e5ea38bdc0..cb0933061006 100644
--- a/arch/powerpc/kernel/cacheinfo.c
+++ b/arch/powerpc/kernel/cacheinfo.c
@@ -690,7 +690,8 @@ show_shared_cpumap(struct kobject *k, struct kobj_attribute *attr, char *buf, bo
mask = &cache->shared_cpu_map;
- return cpumap_print_to_pagebuf(list, buf, mask);
+ return sysfs_emit(buf, list ? "%*pbl\n" : "%*pb\n",
+ cpumask_pr_args(mask));
}
static ssize_t shared_cpu_map_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
diff --git a/arch/powerpc/kernel/cpu_setup_power.c b/arch/powerpc/kernel/cpu_setup_power.c
index 98bd4e6c1770..5de704ac031d 100644
--- a/arch/powerpc/kernel/cpu_setup_power.c
+++ b/arch/powerpc/kernel/cpu_setup_power.c
@@ -286,3 +286,46 @@ void __restore_cpu_power10(void)
init_HFSCR();
init_PMU_HV();
}
+
+void __setup_cpu_power12(unsigned long offset, struct cpu_spec *t)
+{
+ init_FSCR_power10();
+ init_PMU();
+ init_PMU_ISA31();
+
+ if (!init_hvmode_206(t))
+ return;
+
+ mtspr(SPRN_PSSCR, 0);
+ mtspr(SPRN_LPID, 0);
+ mtspr(SPRN_PID, 0);
+ mtspr(SPRN_AMOR, ~0);
+ mtspr(SPRN_PCR, PCR_MASK);
+ init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
+ LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
+ init_HFSCR();
+ init_PMU_HV();
+}
+
+void __restore_cpu_power12(void)
+{
+ u64 msr;
+
+ init_FSCR_power10();
+ init_PMU();
+ init_PMU_ISA31();
+
+ msr = mfmsr();
+ if (!(msr & MSR_HV))
+ return;
+
+ mtspr(SPRN_PSSCR, 0);
+ mtspr(SPRN_LPID, 0);
+ mtspr(SPRN_PID, 0);
+ mtspr(SPRN_AMOR, ~0);
+ mtspr(SPRN_PCR, PCR_MASK);
+ init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
+ LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
+ init_HFSCR();
+ init_PMU_HV();
+}
diff --git a/arch/powerpc/kernel/cpu_specs_book3s_64.h b/arch/powerpc/kernel/cpu_specs_book3s_64.h
index 98d4274a1b6b..26fa40aa34db 100644
--- a/arch/powerpc/kernel/cpu_specs_book3s_64.h
+++ b/arch/powerpc/kernel/cpu_specs_book3s_64.h
@@ -63,6 +63,11 @@
#define COMMON_USER_POWER11 COMMON_USER_POWER10
#define COMMON_USER2_POWER11 COMMON_USER2_POWER10
+#define COMMON_USER_POWER12 COMMON_USER_POWER10
+#define COMMON_USER2_POWER12 (COMMON_USER2_POWER10 | \
+ PPC_FEATURE2_ARCH_3_2)
+
+
static struct cpu_spec cpu_specs[] __initdata = {
{ /* PPC970 */
.pvr_mask = 0xffff0000,
@@ -298,6 +303,20 @@ static struct cpu_spec cpu_specs[] __initdata = {
.cpu_restore = __restore_cpu_power10,
.platform = "power11",
},
+ { /* 3.2-compliant processor, i.e. Power12 "architected" mode */
+ .pvr_mask = 0xffffffff,
+ .pvr_value = 0x0f000008,
+ .cpu_name = "Power12 (architected)",
+ .cpu_features = CPU_FTRS_POWER12,
+ .cpu_user_features = COMMON_USER_POWER12,
+ .cpu_user_features2 = COMMON_USER2_POWER12,
+ .mmu_features = MMU_FTRS_POWER12,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .cpu_setup = __setup_cpu_power12,
+ .cpu_restore = __restore_cpu_power12,
+ .platform = "power12",
+ },
{ /* Power7 */
.pvr_mask = 0xffff0000,
.pvr_value = 0x003f0000,
@@ -485,6 +504,23 @@ static struct cpu_spec cpu_specs[] __initdata = {
.machine_check_early = __machine_check_early_realmode_p10,
.platform = "power11",
},
+ { /* Power12 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00830000,
+ .cpu_name = "Power12 (raw)",
+ .cpu_features = CPU_FTRS_POWER12,
+ .cpu_user_features = COMMON_USER_POWER12,
+ .cpu_user_features2 = COMMON_USER2_POWER12,
+ .mmu_features = MMU_FTRS_POWER12,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .num_pmcs = 6,
+ .pmc_type = PPC_PMC_IBM,
+ .cpu_setup = __setup_cpu_power12,
+ .cpu_restore = __restore_cpu_power12,
+ .machine_check_early = __machine_check_early_realmode_p10,
+ .platform = "power12",
+ },
{ /* Cell Broadband Engine */
.pvr_mask = 0xffff0000,
.pvr_value = 0x00700000,
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
index e5853daa6a48..a87b22f555b2 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -26,6 +26,7 @@
/* Device-tree visible constants follow */
#define ISA_V3_0B 3000
#define ISA_V3_1 3100
+#define ISA_V3_2 3200
#define USABLE_PR (1U << 0)
#define USABLE_OS (1U << 1)
@@ -90,8 +91,6 @@ static void __restore_cpu_cpufeatures(void)
init_pmu_registers();
}
-static char dt_cpu_name[64];
-
static struct cpu_spec __initdata base_cpu_spec = {
.cpu_name = NULL,
.cpu_features = CPU_FTRS_DT_CPU_BASE,
@@ -466,6 +465,35 @@ static int __init feat_enable_mce_power11(struct dt_cpu_feature *f)
return 1;
}
+static void init_pmu_power12(void)
+{
+ init_pmu_power10();
+}
+
+static int __init feat_enable_pmu_power12(struct dt_cpu_feature *f)
+{
+ hfscr_pmu_enable();
+
+ init_pmu_power12();
+ init_pmu_registers = init_pmu_power12;
+
+ cur_cpu_spec->cpu_features |= CPU_FTR_MMCRA;
+ cur_cpu_spec->cpu_user_features |= PPC_FEATURE_PSERIES_PERFMON_COMPAT;
+
+ cur_cpu_spec->num_pmcs = 6;
+ cur_cpu_spec->pmc_type = PPC_PMC_IBM;
+
+ return 1;
+}
+
+static int __init feat_enable_mce_power12(struct dt_cpu_feature *f)
+{
+ cur_cpu_spec->platform = "power12";
+ cur_cpu_spec->machine_check_early = __machine_check_early_realmode_p10;
+
+ return 1;
+}
+
static int __init feat_enable_tm(struct dt_cpu_feature *f)
{
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
@@ -657,9 +685,11 @@ static struct dt_cpu_feature_match __initdata
{"machine-check-power9", feat_enable_mce_power9, 0},
{"machine-check-power10", feat_enable_mce_power10, 0},
{"machine-check-power11", feat_enable_mce_power11, 0},
+ {"machine-check-power12", feat_enable_mce_power12, 0},
{"performance-monitor-power9", feat_enable_pmu_power9, 0},
{"performance-monitor-power10", feat_enable_pmu_power10, 0},
{"performance-monitor-power11", feat_enable_pmu_power10, 0},
+ {"performance-monitor-power12", feat_enable_pmu_power12, 0},
{"event-based-branch-v3", feat_enable, 0},
{"random-number-generator", feat_enable, 0},
{"system-call-vectored", feat_disable, 0},
@@ -714,6 +744,11 @@ static void __init cpufeatures_setup_start(u32 isa)
if (PVR_VER(mfspr(SPRN_PVR)) >= PVR_POWER11)
cur_cpu_spec->cpu_features |= CPU_FTR_P11_PVR;
}
+
+ if (isa >= ISA_V3_2) {
+ cur_cpu_spec->cpu_features |= CPU_FTR_ARCH_32;
+ cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_ARCH_3_2;
+ }
}
static bool __init cpufeatures_process_feature(struct dt_cpu_feature *f)
@@ -1078,6 +1113,7 @@ static int __init count_cpufeatures_subnodes(unsigned long node,
static int __init dt_cpu_ftrs_scan_callback(unsigned long node, const char
*uname, int depth, void *data)
{
+ static char dt_cpu_name[64];
const __be32 *prop;
int count, i;
u32 isa;
@@ -1115,8 +1151,8 @@ static int __init dt_cpu_ftrs_scan_callback(unsigned long node, const char
}
prop = of_get_flat_dt_prop(node, "display-name", NULL);
- if (prop && strlen((char *)prop) != 0) {
- strscpy(dt_cpu_name, (char *)prop, sizeof(dt_cpu_name));
+ if (prop && *(char *)prop != 0) {
+ strscpy(dt_cpu_name, (char *)prop);
cur_cpu_spec->cpu_name = dt_cpu_name;
}
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 028f69158532..d64cce17a4e0 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -533,9 +533,7 @@ static void eeh_rmv_device(struct eeh_dev *edev, void *userdata)
if (rmv_data)
list_add(&edev->rmv_entry, &rmv_data->removed_vf_list);
} else {
- pci_lock_rescan_remove();
pci_stop_and_remove_bus_device(dev);
- pci_unlock_rescan_remove();
}
}
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 63432a33ec49..a54f6f979173 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -713,14 +713,18 @@ p_end: .8byte _end - copy_to_here
_GLOBAL(copy_and_flush)
addi r5,r5,-8
addi r6,r6,-8
-4: li r0,8 /* Use the smallest common */
- /* denominator cache line */
- /* size. This results in */
- /* extra cache line flushes */
- /* but operation is correct. */
- /* Can't get cache line size */
- /* from NACA as it is being */
- /* moved too. */
+4: li r0,8 /* r0 is the number of 8-byte words */
+ /* to copy per cache sync iteration. */
+ /* 8 words * 8 bytes = 64 bytes. 64B is */
+ /* the current default cache line size. */
+ /* This is a loop count, not a byte */
+ /* count. Increasing it may skip */
+ /* dcbst/icbi for lines in between and */
+ /* leave stale instructions in icache. */
+ /* This results in extra cache line */
+ /* flushes but operation is correct. */
+ /* Can't get cache line size from NACA */
+ /* as it is being moved too. */
mtctr r0 /* put # words/line in ctr */
3: addi r6,r6,8 /* copy a cache line */
diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
index 5b88bf72786c..55f9c0c9922a 100644
--- a/arch/powerpc/kernel/interrupt.c
+++ b/arch/powerpc/kernel/interrupt.c
@@ -175,7 +175,7 @@ again:
current_thread_info()->exit_flags &= ~_TIF_RESTOREALL;
regs->exit_result |= ret;
- return ret;
+ return regs->exit_result;
}
#endif
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index ee1b5cb557c9..1ae8384637b5 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -1076,7 +1076,7 @@ int iommu_tce_check_ioba(unsigned long page_shift,
if (ioba < offset)
return -EINVAL;
- if ((ioba + 1) > (offset + size))
+ if ((ioba + npages < ioba) || (ioba - offset + npages > size))
return -EINVAL;
return 0;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index f69de08ad347..15a3c3fd8e70 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -217,8 +217,12 @@ static __always_inline void call_do_softirq(const void *sp)
[sp] "b" (sp), [offset] "i" (THREAD_SIZE - STACK_FRAME_MIN_SIZE),
[callee] "i" (__do_softirq)
: // Clobbers
- "lr", "xer", "ctr", "memory", "cr0", "cr1", "cr5", "cr6",
- "cr7", "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
+ "lr", "xer", "ctr", "memory", "cr0", "cr1", "cr5", "cr6", "cr7", "r0",
+ /* r2 may be clobbered by the callee when using PCREL mode in the ELFv2 ABI. */
+#ifdef CONFIG_PPC_KERNEL_PCREL
+ "r2",
+#endif
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
"r11", "r12"
);
}
@@ -275,8 +279,12 @@ static __always_inline void call_do_irq(struct pt_regs *regs, void *sp)
[sp] "b" (sp), [offset] "i" (THREAD_SIZE - STACK_FRAME_MIN_SIZE),
[callee] "i" (__do_irq)
: // Clobbers
- "lr", "xer", "ctr", "memory", "cr0", "cr1", "cr5", "cr6",
- "cr7", "r0", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
+ "lr", "xer", "ctr", "memory", "cr0", "cr1", "cr5", "cr6", "cr7", "r0",
+ /* r2 may be clobbered by the callee when using PCREL mode in the ELFv2 ABI. */
+#ifdef CONFIG_PPC_KERNEL_PCREL
+ "r2",
+#endif
+ "r4", "r5", "r6", "r7", "r8", "r9", "r10",
"r11", "r12"
);
}
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 3c4ca90e2ab7..4fc52c21fe5d 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -626,19 +626,14 @@ int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val, size_t size)
return -ENXIO;
addr = hose->io_base_virt + port;
- /* WARNING: The generic code is idiotic. It gets passed a pointer
- * to what can be a 1, 2 or 4 byte quantity and always reads that
- * as a u32, which means that we have to correct the location of
- * the data read within those 32 bits for size 1 and 2
- */
switch(size) {
case 1:
- out_8(addr, val >> 24);
+ out_8(addr, val);
return 1;
case 2:
if (port & 1)
return -EINVAL;
- out_le16(addr, val >> 16);
+ out_le16(addr, val);
return 2;
case 4:
if (port & 3)
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 9ed9dde7d231..d218c8cc1f73 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -824,7 +824,6 @@ void __init early_init_devtree(void *params)
fadump_append_bootargs();
/* Scan memory nodes and rebuild MEMBLOCKs */
- early_init_dt_scan_root();
early_init_dt_scan_memory_ppc();
/*
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 53503937de0e..eb9f556b0937 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -86,6 +86,12 @@
*/
#define ADDR(x) (u32)(unsigned long)(x)
+/*
+ * Current Power system firmware caps the PVR list array size at 16 entries
+ * during CAS (Client Architecture Support) negotiation.
+ */
+#define CAS_MAX_PVR_ENTRIES 16
+
#ifdef CONFIG_PPC64
#define OF_WORKAROUNDS 0
#else
@@ -947,7 +953,7 @@ struct option_vector7 {
} __packed;
struct ibm_arch_vec {
- struct { __be32 mask, val; } pvrs[16];
+ struct { __be32 mask, val; } pvrs[18];
u8 num_vectors;
@@ -980,6 +986,10 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
.val = cpu_to_be32(0x003a0000),
},
{
+ .mask = cpu_to_be32(0xffffffff), /* all 2.04-compliant and earlier */
+ .val = cpu_to_be32(0x0f000001),
+ },
+ {
.mask = cpu_to_be32(0xffff0000), /* POWER6 */
.val = cpu_to_be32(0x003e0000),
},
@@ -1012,6 +1022,14 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
.val = cpu_to_be32(0x00820000),
},
{
+ .mask = cpu_to_be32(0xffff0000), /* POWER12 */
+ .val = cpu_to_be32(0x00830000),
+ },
+ {
+ .mask = cpu_to_be32(0xffffffff), /* all 3.2-compliant */
+ .val = cpu_to_be32(0x0f000008),
+ },
+ {
.mask = cpu_to_be32(0xffffffff), /* P11 compliant */
.val = cpu_to_be32(0x0f000007),
},
@@ -1032,13 +1050,9 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
.val = cpu_to_be32(0x0f000003),
},
{
- .mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
+ .mask = cpu_to_be32(0xfffffffd), /* all 2.05-compliant */
.val = cpu_to_be32(0x0f000002),
},
- {
- .mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
- .val = cpu_to_be32(0x0f000001),
- },
},
.num_vectors = NUM_VECTORS(6),
@@ -1048,7 +1062,7 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
.byte1 = 0,
.arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
- .arch_versions3 = OV1_PPC_3_00 | OV1_PPC_3_1,
+ .arch_versions3 = OV1_PPC_3_00 | OV1_PPC_3_1 | OV1_PPC_3_2,
},
.vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
@@ -1403,6 +1417,22 @@ static void __init prom_send_capabilities(void)
ihandle root;
prom_arg_t ret;
u32 cores;
+ int start_index = 0;
+
+ /*
+ * Ensure that when running on Power11 or below hardware, the number
+ * of PVR entries passed during CAS negotiation does not exceed the
+ * firmware-imposed limit of 16.
+ *
+ * Compute the start_index to skip the oldest leading pvrs[] entries
+ * when running on Power11 or below hardware, so that the pointer
+ * passed to ibm,client-architecture-support points to
+ * ibm_architecture_vec.pvrs[start_index], presenting exactly 16
+ * entries to firmware.
+ */
+ if ((ARRAY_SIZE(ibm_architecture_vec_template.pvrs) > CAS_MAX_PVR_ENTRIES) &&
+ (PVR_VER(mfspr(SPRN_PVR)) <= PVR_POWER11))
+ start_index = ARRAY_SIZE(ibm_architecture_vec_template.pvrs) - CAS_MAX_PVR_ENTRIES;
/* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
prom_check_platform_support();
@@ -1427,7 +1457,7 @@ static void __init prom_send_capabilities(void)
if (call_prom_ret("call-method", 3, 2, &ret,
ADDR("ibm,client-architecture-support"),
root,
- ADDR(&ibm_architecture_vec)) == 0) {
+ ADDR(&ibm_architecture_vec.pvrs[start_index])) == 0) {
/* the call exists... */
if (ret)
prom_printf("\nWARNING: ibm,client-architecture"
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 583dc16e9d3c..722dbfb6fbf8 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -394,30 +394,23 @@ static ssize_t manage_flash_write(struct file *file, const char __user *buf,
size_t count, loff_t *off)
{
struct rtas_manage_flash_t *const args_buf = &rtas_manage_flash_data;
- static const char reject_str[] = "0";
- static const char commit_str[] = "1";
- char stkbuf[10];
- int op;
+ unsigned int op;
+ char cmd;
guard(mutex)(&rtas_manage_flash_mutex);
if ((args_buf->status == MANAGE_AUTH) || (count == 0))
return count;
- op = -1;
- if (buf) {
- if (count > 9) count = 9;
- if (copy_from_user (stkbuf, buf, count))
- return -EFAULT;
- if (strncmp(stkbuf, reject_str, strlen(reject_str)) == 0)
- op = RTAS_REJECT_TMP_IMG;
- else if (strncmp(stkbuf, commit_str, strlen(commit_str)) == 0)
- op = RTAS_COMMIT_TMP_IMG;
- }
-
- if (op == -1) { /* buf is empty, or contains invalid string */
+ if (get_user(cmd, buf))
+ return -EFAULT;
+
+ if (cmd == '0')
+ op = RTAS_REJECT_TMP_IMG;
+ else if (cmd == '1')
+ op = RTAS_COMMIT_TMP_IMG;
+ else
return -EINVAL;
- }
manage_flash(args_buf, op);
return count;
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index fccf96e897f6..206c825225c2 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -54,6 +54,10 @@ int rtas_pci_dn_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
if (!config_access_valid(pdn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
#ifdef CONFIG_EEH
+ if (pdn->edev &&
+ (pdn->edev->mode & EEH_DEV_REMOVED))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
if (pdn->edev && pdn->edev->pe &&
(pdn->edev->pe->state & EEH_PE_CFG_BLOCKED))
return PCIBIOS_SET_FAILED;
@@ -105,6 +109,10 @@ int rtas_pci_dn_write_config(struct pci_dn *pdn, int where, int size, u32 val)
if (!config_access_valid(pdn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
#ifdef CONFIG_EEH
+ if (pdn->edev &&
+ (pdn->edev->mode & EEH_DEV_REMOVED))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
if (pdn->edev && pdn->edev->pe &&
(pdn->edev->pe->state & EEH_PE_CFG_BLOCKED))
return PCIBIOS_SET_FAILED;
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
index 6336ec9aedd0..fd40864bdb70 100644
--- a/arch/powerpc/kernel/rtasd.c
+++ b/arch/powerpc/kernel/rtasd.c
@@ -10,6 +10,7 @@
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/of.h>
+#include <linux/overflow.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
@@ -160,25 +161,17 @@ static void printk_log_rtas(char *buf, int len)
static int log_rtas_len(char * buf)
{
- int len;
+ size_t len;
struct rtas_error_log *err;
- uint32_t extended_log_length;
+ u32 extended_log_length;
- /* rtas fixed header */
- len = 8;
err = (struct rtas_error_log *)buf;
- extended_log_length = rtas_error_extended_log_length(err);
- if (rtas_error_extended(err) && extended_log_length) {
-
- /* extended header */
- len += extended_log_length;
- }
+ extended_log_length = rtas_error_extended(err) ? rtas_error_extended_log_length(err) : 0;
+ len = struct_size(err, buffer, extended_log_length);
if (rtas_error_log_max == 0)
rtas_error_log_max = rtas_get_error_log_max();
-
- if (len > rtas_error_log_max)
- len = rtas_error_log_max;
+ len = min(len, rtas_error_log_max);
return len;
}
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 67c545f61f0d..4afaba19b586 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -304,6 +304,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
break;
case 0x004e: /* POWER9 bits 12-15 give chip type */
case 0x0080: /* POWER10 bit 12 gives SMT8/4 */
+ case 0x0083: /* POWER12 bit 12 gives SMT8/4 */
maj = (pvr >> 8) & 0x0F;
min = pvr & 0xFF;
break;
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 3467f86fd78f..6a5a5469aaae 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -289,6 +289,9 @@ void smp_muxed_ipi_set_message(int cpu, int msg)
void smp_muxed_ipi_message_pass(int cpu, int msg)
{
+ if (!smp_ops->cause_ipi)
+ return;
+
smp_muxed_ipi_set_message(cpu, msg);
/*
diff --git a/arch/powerpc/kernel/syscall.c b/arch/powerpc/kernel/syscall.c
index a9da2af6efa8..fbefe1927b10 100644
--- a/arch/powerpc/kernel/syscall.c
+++ b/arch/powerpc/kernel/syscall.c
@@ -2,7 +2,6 @@
#include <linux/compat.h>
#include <linux/context_tracking.h>
-#include <linux/randomize_kstack.h>
#include <linux/entry-common.h>
#include <asm/interrupt.h>
@@ -19,8 +18,13 @@ notrace long system_call_exception(struct pt_regs *regs, unsigned long r0)
long ret;
syscall_fn f;
- add_random_kstack_offset();
- r0 = syscall_enter_from_user_mode(regs, r0);
+ if (unlikely(!syscall_enter_from_user_mode_randomize_stack(regs, &r0))) {
+ clear_thread_flag(TIF_SYSCALL_RET);
+ return syscall_get_error(current, regs);
+ }
+
+ if (unlikely(test_and_clear_thread_flag(TIF_SYSCALL_RET)))
+ return syscall_get_error(current, regs);
if (unlikely(r0 >= NR_syscalls)) {
if (unlikely(trap_is_unsupported_scv(regs))) {
diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl
index 4fcc7c58a105..cfbb70039ff0 100644
--- a/arch/powerpc/kernel/syscalls/syscall.tbl
+++ b/arch/powerpc/kernel/syscalls/syscall.tbl
@@ -562,3 +562,4 @@
469 common file_setattr sys_file_setattr
470 common listns sys_listns
471 nospu rseq_slice_yield sys_rseq_slice_yield
+472 common fchroot sys_fchroot
diff --git a/arch/powerpc/kernel/vdso/gettimeofday.S b/arch/powerpc/kernel/vdso/gettimeofday.S
index 1c8e51691bf8..c635cd1e77be 100644
--- a/arch/powerpc/kernel/vdso/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso/gettimeofday.S
@@ -67,9 +67,11 @@
* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
*
*/
+#if defined(__powerpc64__) || defined(CONFIG_COMPAT_32BIT_TIME)
V_FUNCTION_BEGIN(__kernel_gettimeofday)
cvdso_call __c_kernel_gettimeofday
V_FUNCTION_END(__kernel_gettimeofday)
+#endif
/*
* Exact prototype of clock_gettime()
@@ -77,9 +79,11 @@ V_FUNCTION_END(__kernel_gettimeofday)
* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp);
*
*/
+#if defined(__powerpc64__) || defined(CONFIG_COMPAT_32BIT_TIME)
V_FUNCTION_BEGIN(__kernel_clock_gettime)
cvdso_call __c_kernel_clock_gettime
V_FUNCTION_END(__kernel_clock_gettime)
+#endif
/*
* Exact prototype of clock_gettime64()
@@ -99,9 +103,11 @@ V_FUNCTION_END(__kernel_clock_gettime64)
* int __kernel_clock_getres(clockid_t clock_id, struct timespec *res);
*
*/
+#if defined(__powerpc64__) || defined(CONFIG_COMPAT_32BIT_TIME)
V_FUNCTION_BEGIN(__kernel_clock_getres)
cvdso_call __c_kernel_clock_getres
V_FUNCTION_END(__kernel_clock_getres)
+#endif
/*
* Exact prototype of clock_getres_time64()
@@ -122,6 +128,8 @@ V_FUNCTION_END(__kernel_clock_getres_time64)
* time_t time(time *t);
*
*/
+#if defined(__powerpc64__) || defined(CONFIG_COMPAT_32BIT_TIME)
V_FUNCTION_BEGIN(__kernel_time)
cvdso_call __c_kernel_time call_time=1
V_FUNCTION_END(__kernel_time)
+#endif
diff --git a/arch/powerpc/kernel/vdso/vdso32.lds.S b/arch/powerpc/kernel/vdso/vdso32.lds.S
index 3f384a2526ae..5e87c18fd282 100644
--- a/arch/powerpc/kernel/vdso/vdso32.lds.S
+++ b/arch/powerpc/kernel/vdso/vdso32.lds.S
@@ -119,13 +119,15 @@ VERSION
{
VDSO_VERSION_STRING {
global:
- __kernel_get_syscall_map;
+#ifdef CONFIG_COMPAT_32BIT_TIME
__kernel_gettimeofday;
__kernel_clock_gettime;
- __kernel_clock_gettime64;
__kernel_clock_getres;
- __kernel_clock_getres_time64;
__kernel_time;
+#endif /* CONFIG_COMPAT_32BIT_TIME */
+ __kernel_get_syscall_map;
+ __kernel_clock_gettime64;
+ __kernel_clock_getres_time64;
__kernel_get_tbfreq;
__kernel_sync_dicache;
__kernel_sigtramp32;
diff --git a/arch/powerpc/kernel/vdso/vgettimeofday.c b/arch/powerpc/kernel/vdso/vgettimeofday.c
index 3c194e1ab562..4b712fb01a3f 100644
--- a/arch/powerpc/kernel/vdso/vgettimeofday.c
+++ b/arch/powerpc/kernel/vdso/vgettimeofday.c
@@ -18,23 +18,25 @@ int __c_kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res,
return __cvdso_clock_getres_data(vd, clock_id, res);
}
#else
+#ifdef CONFIG_COMPAT_32BIT_TIME
int __c_kernel_clock_gettime(clockid_t clock, struct old_timespec32 *ts,
const struct vdso_time_data *vd)
{
return __cvdso_clock_gettime32_data(vd, clock, ts);
}
-int __c_kernel_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts,
- const struct vdso_time_data *vd)
-{
- return __cvdso_clock_gettime_data(vd, clock, ts);
-}
-
int __c_kernel_clock_getres(clockid_t clock_id, struct old_timespec32 *res,
const struct vdso_time_data *vd)
{
return __cvdso_clock_getres_time32_data(vd, clock_id, res);
}
+#endif /* CONFIG_COMPAT_32BIT_TIME */
+
+int __c_kernel_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts,
+ const struct vdso_time_data *vd)
+{
+ return __cvdso_clock_gettime_data(vd, clock, ts);
+}
int __c_kernel_clock_getres_time64(clockid_t clock_id, struct __kernel_timespec *res,
const struct vdso_time_data *vd)
@@ -43,6 +45,7 @@ int __c_kernel_clock_getres_time64(clockid_t clock_id, struct __kernel_timespec
}
#endif
+#if defined(__powerpc64__) || defined(CONFIG_COMPAT_32BIT_TIME)
int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz,
const struct vdso_time_data *vd)
{
@@ -53,3 +56,4 @@ __kernel_old_time_t __c_kernel_time(__kernel_old_time_t *time, const struct vdso
{
return __cvdso_time_data(vd, time);
}
+#endif