diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-08-23 10:07:52 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-08-23 10:07:52 +0000 |
commit | 555f34de9a565ba9e2abf9ea1e4a3a3f019fe5c0 (patch) | |
tree | d81c7f5c09fcf12547aba40e68ab8945b48d2f0d /sys/arch | |
parent | 6f30adc27aeee1bf4f4bcaafab1f71a3f33f00ba (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.h | 11 | ||||
-rw-r--r-- | sys/arch/powerpc64/include/cpufunc.h | 11 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/cpu.c | 46 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/machdep.c | 9 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/pmap.c | 11 |
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++) { |