diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2017-05-24 13:33:01 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2017-05-24 13:33:01 +0000 |
commit | 41d468b9e505cc0805b5cdff947859554896fe8c (patch) | |
tree | dbb8443ace184562a58990021a3c03e71c6c88e1 | |
parent | 3d5d9c3cc643a0562be079f11040d4bc73984726 (diff) |
Add an idle cycle implementation for R4600/R5000/RM7000 CPUs and their
derivatives. This lets the kernel utilize the CPUs' Standby Mode to
reduce the power consumption of an idle system.
Suggested by and input from miod@.
He also tested this patch on an RM7000 O2.
-rw-r--r-- | sys/arch/mips64/include/cpu.h | 5 | ||||
-rw-r--r-- | sys/arch/mips64/mips64/context.S | 35 | ||||
-rw-r--r-- | sys/arch/mips64/mips64/cpu.c | 26 |
3 files changed, 59 insertions, 7 deletions
diff --git a/sys/arch/mips64/include/cpu.h b/sys/arch/mips64/include/cpu.h index 5213837ace9..260e8585361 100644 --- a/sys/arch/mips64/include/cpu.h +++ b/sys/arch/mips64/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.116 2017/04/20 15:42:26 visa Exp $ */ +/* $OpenBSD: cpu.h,v 1.117 2017/05/24 13:33:00 visa Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -234,6 +234,9 @@ extern struct cpu_info *cpu_info_list; #define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) +extern void (*cpu_idle_cycle_func)(void); +#define cpu_idle_cycle() (*cpu_idle_cycle_func)() + #ifdef MULTIPROCESSOR #define MAXCPUS 4 #define getcurcpu() hw_getcurcpu() diff --git a/sys/arch/mips64/mips64/context.S b/sys/arch/mips64/mips64/context.S index 7843e76ae52..c5cbe1e25dd 100644 --- a/sys/arch/mips64/mips64/context.S +++ b/sys/arch/mips64/mips64/context.S @@ -1,4 +1,4 @@ -/* $OpenBSD: context.S,v 1.59 2017/04/20 15:42:26 visa Exp $ */ +/* $OpenBSD: context.S,v 1.60 2017/05/24 13:33:00 visa Exp $ */ /* * Copyright (c) 2002-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -80,13 +80,38 @@ LEAF(cpu_idle_leave, 0) NOP END(cpu_idle_leave) -LEAF(cpu_idle_cycle, 0) -#ifdef CPU_OCTEON +LEAF(cpu_idle_cycle_nop, 0) + j ra + NOP +END(cpu_idle_cycle_nop) + +LEAF(cpu_idle_cycle_wait, 0) wait -#endif j ra NOP -END(cpu_idle_cycle) +END(cpu_idle_cycle_wait) + +LEAF(cpu_idle_cycle_rm7k, 0) + /* + * RM7000 errata #38: The R4600, R4640, R4700, R5000, RM52xx, + * and RM7xxx processors do not handle bus signalling properly + * in the standby mode, which can cause incorrect behaviour + * upon leaving the mode. This can be avoided by flushing + * any writes from the pipeline before the WAIT instruction + * is executed. + */ + mfc0 a0, COP_0_STATUS_REG # save status + ori a1, a0, SR_INT_ENAB + xori a1, SR_INT_ENAB + mtc0 a1, COP_0_STATUS_REG # disable interrupts + sync # flush pending writes + mtc0 a1, COP_0_STATUS_REG # stall until W stage + wait # enter standby mode + mtc0 a0, COP_0_STATUS_REG # stall until W stage, + # and restore status + j ra + NOP +END(cpu_idle_cycle_rm7k) /* * cpu_switchto_asm(struct proc *oldproc, struct proc *newproc) diff --git a/sys/arch/mips64/mips64/cpu.c b/sys/arch/mips64/mips64/cpu.c index bb40e5b77e7..53aed7c95da 100644 --- a/sys/arch/mips64/mips64/cpu.c +++ b/sys/arch/mips64/mips64/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.67 2017/05/11 15:42:10 visa Exp $ */ +/* $OpenBSD: cpu.c,v 1.68 2017/05/24 13:33:00 visa Exp $ */ /* * Copyright (c) 1997-2004 Opsycon AB (www.opsycon.se) @@ -50,6 +50,11 @@ struct cpu_info *cpu_info_secondaries; struct cpuset cpus_running; #endif +extern void cpu_idle_cycle_nop(void); +extern void cpu_idle_cycle_rm7k(void); +extern void cpu_idle_cycle_wait(void); +void (*cpu_idle_cycle_func)(void) = cpu_idle_cycle_nop; + vaddr_t cache_valias_mask; int cpu_has_userlocal; @@ -366,6 +371,25 @@ cpuattach(struct device *parent, struct device *dev, void *aux) else printf("%d way", ci->ci_l3.sets); } + + if (cpuno == 0) { + switch (ch->type) { + case MIPS_R4600: + case MIPS_R4700: + case MIPS_R5000: + case MIPS_RM52X0: + case MIPS_RM7000: + cpu_idle_cycle_func = cpu_idle_cycle_rm7k; + break; + case MIPS_CN50XX: + case MIPS_CN61XX: + case MIPS_CN71XX: + case MIPS_CN73XX: + cpu_idle_cycle_func = cpu_idle_cycle_wait; + break; + } + } + printf("\n"); #ifdef DEBUG |