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