summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/sparc64/include/mdesc.h6
-rw-r--r--sys/arch/sparc64/sparc64/autoconf.c42
-rw-r--r--sys/arch/sparc64/sparc64/lock_machdep.c15
-rw-r--r--sys/arch/sparc64/sparc64/locore.s12
-rw-r--r--sys/arch/sparc64/sparc64/mdesc.c50
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);
+}