diff options
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sparc64/include/mdesc.h | 6 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/autoconf.c | 42 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/lock_machdep.c | 15 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/locore.s | 12 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/mdesc.c | 50 |
5 files changed, 117 insertions, 8 deletions
diff --git a/sys/arch/sparc64/include/mdesc.h b/sys/arch/sparc64/include/mdesc.h index 5e5581bd739..bacc926141a 100644 --- a/sys/arch/sparc64/include/mdesc.h +++ b/sys/arch/sparc64/include/mdesc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mdesc.h,v 1.2 2009/05/10 12:37:01 kettenis Exp $ */ +/* $OpenBSD: mdesc.h,v 1.3 2014/11/30 22:26:14 kettenis Exp $ */ /* * Copyright (c) 2009 Mark Kettenis * @@ -42,7 +42,9 @@ extern size_t mdesc_len; void mdesc_init(void); uint64_t mdesc_get_prop_val(int, const char *); -const char * mdesc_get_prop_str(int, const char *); +const char *mdesc_get_prop_str(int, const char *); +const char *mdesc_get_prop_data(int, const char *, size_t *); int mdesc_find(const char *, uint64_t); int mdesc_find_child(int, const char *, uint64_t); +int mdesc_find_node(const char *); #endif diff --git a/sys/arch/sparc64/sparc64/autoconf.c b/sys/arch/sparc64/sparc64/autoconf.c index 956262d6389..2a1a7b020e9 100644 --- a/sys/arch/sparc64/sparc64/autoconf.c +++ b/sys/arch/sparc64/sparc64/autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.c,v 1.122 2014/11/26 20:06:53 stsp Exp $ */ +/* $OpenBSD: autoconf.c,v 1.123 2014/11/30 22:26:14 kettenis Exp $ */ /* $NetBSD: autoconf.c,v 1.51 2001/07/24 19:32:11 eeh Exp $ */ /* @@ -648,8 +648,46 @@ void cpu_configure() { #ifdef SUN4V - if (CPU_ISSUN4V) + int pause = 0; + + if (CPU_ISSUN4V) { + const char *prop; + size_t len; + int idx; + mdesc_init(); + idx = mdesc_find_node("cpu"); + prop = mdesc_get_prop_data(idx, "hwcap-list", &len); + if (prop) { + while (len > 0) { + if (strcmp(prop, "pause") == 0) + pause = 1; + len -= strlen(prop) + 1; + prop += strlen(prop) + 1; + } + } + } + + if (pause) { + struct sun4v_patch { + u_int32_t addr; + u_int32_t insn; + } *p; + paddr_t pa; + + extern struct sun4v_patch sun4v_pause_patch; + extern struct sun4v_patch sun4v_pause_patch_end; + + /* + * Use physical addresses to patch since kernel .text + * is already mapped read-only at this point. + */ + for (p = &sun4v_pause_patch; p < &sun4v_pause_patch_end; p++) { + pmap_extract(pmap_kernel(), (vaddr_t)p->addr, &pa); + stwa(pa, ASI_PHYS_NON_CACHED, p->insn); + flush((void *)(vaddr_t)p->addr); + } + } #endif if (obd.version == BOOTDATA_VERSION && diff --git a/sys/arch/sparc64/sparc64/lock_machdep.c b/sys/arch/sparc64/sparc64/lock_machdep.c index 92d59254703..f361ffb8f7c 100644 --- a/sys/arch/sparc64/sparc64/lock_machdep.c +++ b/sys/arch/sparc64/sparc64/lock_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lock_machdep.c,v 1.7 2014/03/29 18:09:30 guenther Exp $ */ +/* $OpenBSD: lock_machdep.c,v 1.8 2014/11/30 22:26:14 kettenis Exp $ */ /* * Copyright (c) 2007 Artur Grabowski <art@openbsd.org> @@ -53,7 +53,10 @@ extern int __mp_lock_spinout; * effectively nops, executing them on earlier non-CMT processors is * harmless, so we make this the default. * - * On SPARC64 VI and it successors we execute the processor-specific + * On SPARC T4 and later, we can use the processor-specific pause + * instruction. + * + * On SPARC64 VI and its successors we execute the processor-specific * sleep instruction. */ static __inline void @@ -63,6 +66,14 @@ __mp_lock_spin_hook(void) "999: rd %%ccr, %%g0 \n" " rd %%ccr, %%g0 \n" " rd %%ccr, %%g0 \n" + " .section .sun4v_pause_patch, \"ax\" \n" + " .word 999b \n" + " .word 0xb7802080 ! pause 128 \n" + " .word 999b + 4 \n" + " nop \n" + " .word 999b + 8 \n" + " nop \n" + " .previous \n" " .section .sun4u_mtp_patch, \"ax\" \n" " .word 999b \n" " .word 0x81b01060 ! sleep \n" diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s index f0d35a494b2..dfec6907347 100644 --- a/sys/arch/sparc64/sparc64/locore.s +++ b/sys/arch/sparc64/sparc64/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.178 2014/11/24 10:55:49 kettenis Exp $ */ +/* $OpenBSD: locore.s,v 1.179 2014/11/30 22:26:14 kettenis Exp $ */ /* $NetBSD: locore.s,v 1.137 2001/08/13 06:10:10 jdolecek Exp $ */ /* @@ -106,6 +106,16 @@ _C_LABEL(sun4v_patch): _C_LABEL(sun4v_patch_end): .previous + .section .sun4v_pause_patch, "ax" + .globl _C_LABEL(sun4v_pause_patch) +_C_LABEL(sun4v_pause_patch): + .previous + + .section .sun4v_pause_patch_end, "ax" + .globl _C_LABEL(sun4v_pause_patch_end) +_C_LABEL(sun4v_pause_patch_end): + .previous + #ifdef MULTIPROCESSOR .section .sun4v_mp_patch, "ax" .globl _C_LABEL(sun4v_mp_patch) diff --git a/sys/arch/sparc64/sparc64/mdesc.c b/sys/arch/sparc64/sparc64/mdesc.c index 2d905f4ef72..73d51353bc2 100644 --- a/sys/arch/sparc64/sparc64/mdesc.c +++ b/sys/arch/sparc64/sparc64/mdesc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mdesc.c,v 1.6 2014/11/16 12:30:59 deraadt Exp $ */ +/* $OpenBSD: mdesc.c,v 1.7 2014/11/30 22:26:15 kettenis Exp $ */ /* * Copyright (c) 2009 Mark Kettenis * @@ -138,6 +138,32 @@ mdesc_get_prop_str(int idx, const char *name) return (NULL); } +const char * +mdesc_get_prop_data(int idx, const char *name, size_t *len) +{ + struct md_header *hdr; + struct md_element *elem; + const char *name_blk; + const char *data_blk; + const char *str; + + hdr = (struct md_header *)mdesc; + elem = (struct md_element *)(mdesc + sizeof(struct md_header)); + name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz; + data_blk = name_blk + hdr->name_blk_sz; + + while (elem[idx].tag != 'E') { + str = name_blk + elem[idx].name_offset; + if (elem[idx].tag == 'd' && strcmp(str, name) == 0) { + *len = elem[idx].d.y.data_len; + return (data_blk + elem[idx].d.y.data_offset); + } + idx++; + } + + return (NULL); +} + int mdesc_find(const char *name, uint64_t cfg_handle) { @@ -188,3 +214,25 @@ mdesc_find_child(int idx, const char *name, uint64_t cfg_handle) return (-1); } + +int +mdesc_find_node(const char *name) +{ + struct md_header *hdr; + struct md_element *elem; + const char *name_blk; + const char *str; + int idx; + + hdr = (struct md_header *)mdesc; + elem = (struct md_element *)(mdesc + sizeof(struct md_header)); + name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz; + + for (idx = 0; elem[idx].tag == 'N'; idx = elem[idx].d.val) { + str = name_blk + elem[idx].name_offset; + if (str && strcmp(str, name) == 0) + return (idx); + } + + return (-1); +} |