summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2020-08-23 10:07:52 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2020-08-23 10:07:52 +0000
commit555f34de9a565ba9e2abf9ea1e4a3a3f019fe5c0 (patch)
treed81c7f5c09fcf12547aba40e68ab8945b48d2f0d /sys/arch
parent6f30adc27aeee1bf4f4bcaafab1f71a3f33f00ba (diff)
Add support for POWER8 (and maybe earlier) CPUs. Not sure if this works on
real hardware, but it gets the kernel booting on QEMU emulating a POWER8 CPU so it's a step in the right direction. This establishes a way to distinguish CPU features based on the AT_HWCAP and AT_HWCAP2 features documented in the ELF ABI. Also use this to determine the availability of the DARN instruction instead of keying of the processor model.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/powerpc64/include/cpu.h11
-rw-r--r--sys/arch/powerpc64/include/cpufunc.h11
-rw-r--r--sys/arch/powerpc64/powerpc64/cpu.c46
-rw-r--r--sys/arch/powerpc64/powerpc64/machdep.c9
-rw-r--r--sys/arch/powerpc64/powerpc64/pmap.c11
5 files changed, 64 insertions, 24 deletions
diff --git a/sys/arch/powerpc64/include/cpu.h b/sys/arch/powerpc64/include/cpu.h
index bc01c1fe6a5..2c716378f66 100644
--- a/sys/arch/powerpc64/include/cpu.h
+++ b/sys/arch/powerpc64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.23 2020/07/23 16:21:44 kettenis Exp $ */
+/* $OpenBSD: cpu.h,v 1.24 2020/08/23 10:07:51 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -160,6 +160,15 @@ void cpu_startclock(void);
#define curpcb curcpu()->ci_curpcb
+extern uint32_t cpu_features;
+extern uint32_t cpu_features2;
+
+#define PPC_FEATURE2_ARCH_3_00 0x00800000
+#define PPC_FEATURE2_DARN 0x00200000
+
+void cpu_init_features(void);
+void cpu_init(void);
+
static inline unsigned int
cpu_rnd_messybits(void)
{
diff --git a/sys/arch/powerpc64/include/cpufunc.h b/sys/arch/powerpc64/include/cpufunc.h
index e9228587f3e..d6c2cbd31d0 100644
--- a/sys/arch/powerpc64/include/cpufunc.h
+++ b/sys/arch/powerpc64/include/cpufunc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpufunc.h,v 1.7 2020/07/10 23:22:48 gkoehler Exp $ */
+/* $OpenBSD: cpufunc.h,v 1.8 2020/08/23 10:07:51 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -131,6 +131,12 @@ mtdec(uint32_t value)
__asm volatile ("mtdec %0" :: "r"(value));
}
+static inline void
+mtsdr1(uint64_t value)
+{
+ __asm volatile ("mtsdr1 %0" :: "r"(value));
+}
+
static inline uint32_t
mfpvr(void)
{
@@ -153,6 +159,9 @@ mtlpcr(uint64_t value)
__asm volatile ("mtspr 318, %0" :: "r"(value));
}
+#define LPCR_LPES 0x0000000000000008UL
+#define LPCR_HVICE 0x0000000000000002UL
+
static inline void
mtptcr(uint64_t value)
{
diff --git a/sys/arch/powerpc64/powerpc64/cpu.c b/sys/arch/powerpc64/powerpc64/cpu.c
index 43a1b8ed98f..38b53fb6668 100644
--- a/sys/arch/powerpc64/powerpc64/cpu.c
+++ b/sys/arch/powerpc64/powerpc64/cpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.c,v 1.16 2020/08/14 12:13:01 kettenis Exp $ */
+/* $OpenBSD: cpu.c,v 1.17 2020/08/23 10:07:51 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -56,6 +56,9 @@ struct cpu_version cpu_version[] = {
};
char cpu_model[64];
+uint32_t cpu_features;
+uint32_t cpu_features2;
+
uint64_t tb_freq = 512000000; /* POWER8, POWER9 */
struct cpu_info cpu_info[MAXCPUS];
@@ -175,13 +178,9 @@ cpu_attach(struct device *parent, struct device *dev, void *aux)
level++;
}
- if (CPU_IS_PRIMARY(ci)) {
- switch (CPU_VERSION(pvr)) {
- case CPU_IBMPOWER9:
- timeout_set(&cpu_darn_to, cpu_darn, NULL);
- cpu_darn(NULL);
- break;
- }
+ if (CPU_IS_PRIMARY(ci) && (cpu_features2 & PPC_FEATURE2_DARN)) {
+ timeout_set(&cpu_darn_to, cpu_darn, NULL);
+ cpu_darn(NULL);
}
#ifdef MULTIPROCESSOR
@@ -216,6 +215,31 @@ cpu_attach(struct device *parent, struct device *dev, void *aux)
}
void
+cpu_init_features(void)
+{
+ uint32_t pvr = mfpvr();
+
+ switch (CPU_VERSION(pvr)) {
+ case CPU_IBMPOWER9:
+ cpu_features2 |= PPC_FEATURE2_ARCH_3_00;
+ cpu_features2 |= PPC_FEATURE2_DARN;
+ break;
+ }
+}
+
+void
+cpu_init(void)
+{
+ uint64_t lpcr = LPCR_LPES;
+
+ if (cpu_features2 & PPC_FEATURE2_ARCH_3_00)
+ lpcr |= LPCR_HVICE;
+
+ mtlpcr(lpcr);
+ isync();
+}
+
+void
cpu_darn(void *arg)
{
uint64_t value;
@@ -252,11 +276,7 @@ cpu_bootstrap(void)
msr = mfmsr();
mtmsr(msr | (PSL_ME|PSL_RI));
-#define LPCR_LPES 0x0000000000000008UL
-#define LPCR_HVICE 0x0000000000000002UL
-
- mtlpcr(LPCR_LPES | LPCR_HVICE);
- isync();
+ cpu_init();
pmap_bootstrap_cpu();
diff --git a/sys/arch/powerpc64/powerpc64/machdep.c b/sys/arch/powerpc64/powerpc64/machdep.c
index 2f36148c222..96e36a550c1 100644
--- a/sys/arch/powerpc64/powerpc64/machdep.c
+++ b/sys/arch/powerpc64/powerpc64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.56 2020/08/17 16:55:41 kettenis Exp $ */
+/* $OpenBSD: machdep.c,v 1.57 2020/08/23 10:07:51 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -171,11 +171,8 @@ init_powernv(void *fdt, void *tocbase)
msr = mfmsr();
mtmsr(msr | (PSL_ME|PSL_RI));
-#define LPCR_LPES 0x0000000000000008UL
-#define LPCR_HVICE 0x0000000000000002UL
-
- mtlpcr(LPCR_LPES | LPCR_HVICE);
- isync();
+ cpu_init_features();
+ cpu_init();
/* Add all memory. */
node = fdt_find_node("/");
diff --git a/sys/arch/powerpc64/powerpc64/pmap.c b/sys/arch/powerpc64/powerpc64/pmap.c
index 4c69b41d163..6dfee10cace 100644
--- a/sys/arch/powerpc64/powerpc64/pmap.c
+++ b/sys/arch/powerpc64/powerpc64/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.42 2020/08/21 13:42:02 kettenis Exp $ */
+/* $OpenBSD: pmap.c,v 1.43 2020/08/23 10:07:51 kettenis Exp $ */
/*
* Copyright (c) 2015 Martin Pieuchot
@@ -1451,8 +1451,13 @@ pmap_bootstrap_cpu(void)
/* Clear TLB. */
tlbia();
- /* Set partition table. */
- mtptcr((paddr_t)pmap_pat | PATSIZE);
+ if (cpu_features2 & PPC_FEATURE2_ARCH_3_00) {
+ /* Set partition table. */
+ mtptcr((paddr_t)pmap_pat | PATSIZE);
+ } else {
+ /* Set page table. */
+ mtsdr1((paddr_t)pmap_ptable | HTABSIZE);
+ }
/* Load SLB. */
for (idx = 0; idx < 31; idx++) {