1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/asm_linkage.h> 27 #include <sys/asm_misc.h> 28 29 #if defined(lint) || defined(__lint) 30 #include <sys/types.h> 31 #include "acpi.h" 32 #endif /* lint */ 33 34 /* 35 * Implementation as specific by ACPI 3.0 specification 36 * section 5.2.10.1 37 * 38 * Global Lock Structure within the FACS 39 * 40 * |-----------------------------------------------------------------------| 41 * | Field | Bit Length | Bit Offset | Description | 42 * |---------|------------|------------|-----------------------------------| 43 * | Pending | 1 | 0 | Non-zero indicates that a request | 44 * | | | | for ownership of the global lock | 45 * | | | | is pending. | 46 * |---------|------------|------------|-----------------------------------| 47 * | Owned | 1 | 1 | Non-zero indicates that the Global| 48 * | | | | lock is owned. | 49 * |---------|------------|------------|-----------------------------------| 50 * | Reserved| 30 | 2 | Reserved for future use | 51 * |---------|------------|------------|-----------------------------------| 52 */ 53 54 /* Offset of GlobalLock element in FACS structure */ 55 #define GlobalLock 0x10 56 57 #if defined(lint) || defined(__lint) 58 59 /* ARGSUSED */ 60 UINT32 61 __acpi_acquire_global_lock(void *Facs) 62 { return (0); } 63 64 #else /* lint */ 65 66 #if defined(__amd64) 67 ENTRY(__acpi_acquire_global_lock) 68 movq $0xff, %rax / error return if FACS is null 69 orq %rdi, %rdi / %rdi contains pointer to FACS 70 jz 1f 71 leaq GlobalLock(%rdi), %rdi / make %rdi point at the lock 72 0: 73 movl (%rdi), %eax / get current value of Global Lock 74 movl %eax, %edx 75 andl $0xFFFFFFFE, %edx / Clear pending bit 76 btsl $1, %edx / Check and set owner bit 77 adcl $0, %edx / If owned, set pending bit 78 lock 79 cmpxchgl %edx, (%rdi) / Attempt to set new value 80 jnz 0b / If not set, try again 81 cmpb $3, %dl / Was it acquired or marked pending? 82 sbbq %rax, %rax / acquired = -1, pending = 0 83 1: 84 ret 85 SET_SIZE(__acpi_acquire_global_lock) 86 87 #elif defined(__i386) 88 89 ENTRY(__acpi_acquire_global_lock) 90 movl $0xff, %eax / error return if FACS is null 91 movl 4(%esp), %ecx / %ecx contains pointer to FACS 92 orl %ecx, %ecx 93 jz 1f 94 leal GlobalLock(%ecx), %ecx / make %ecx point at the lock 95 0: 96 movl (%ecx), %eax 97 movl %eax, %edx 98 andl $0xFFFFFFFE, %edx 99 btsl $1, %edx 100 adcl $0, %edx 101 lock 102 cmpxchgl %edx, (%ecx) 103 jnz 0b 104 cmpb $3, %dl 105 sbbl %eax, %eax 106 1: 107 ret 108 SET_SIZE(__acpi_acquire_global_lock) 109 110 #endif /* i386 */ 111 112 #endif /* lint */ 113 114 115 #if defined(lint) || defined(__lint) 116 117 /* ARGSUSED */ 118 UINT32 119 __acpi_release_global_lock(void *Facs) 120 { return (0); } 121 122 #else /* lint */ 123 124 #if defined(__amd64) 125 ENTRY(__acpi_release_global_lock) 126 xorq %rax, %rax / error return if FACS is null 127 orq %rdi, %rdi / %rdi contains pointer to FACS 128 jz 1f 129 leaq GlobalLock(%rdi), %rdi / make %rdi point at the lock 130 0: 131 movl (%rdi), %eax 132 movl %eax, %edx 133 andl $0xFFFFFFFC, %edx 134 lock 135 cmpxchgl %edx, (%rdi) 136 jnz 0b 137 andq $1, %rax 138 1: 139 ret 140 SET_SIZE(__acpi_release_global_lock) 141 142 #elif defined(__i386) 143 144 ENTRY(__acpi_release_global_lock) 145 xorl %eax, %eax / error return if FACS is null 146 movl 4(%esp), %ecx / %ecx contains pointer to FACS 147 orl %ecx, %ecx 148 jz 1f 149 leal GlobalLock(%ecx), %ecx / make %ecx point at the lock 150 0: 151 movl (%ecx), %eax 152 movl %eax, %edx 153 andl $0xFFFFFFFC, %edx 154 lock 155 cmpxchgl %edx, (%ecx) 156 jnz 0b 157 andl $1, %eax 158 1: 159 ret 160 SET_SIZE(__acpi_release_global_lock) 161 162 #endif /* i386 */ 163 164 #endif /* lint */ 165 166 167 /* 168 * execute WBINVD instruction 169 */ 170 171 #if defined(lint) || defined(__lint) 172 173 /* ARGSUSED */ 174 void 175 __acpi_wbinvd(void) 176 { } 177 178 #else /* lint */ 179 180 ENTRY(__acpi_wbinvd) 181 wbinvd 182 ret 183 SET_SIZE(__acpi_wbinvd) 184 185 #endif /* lint */ 186