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 /* 27 * Copyright 2019 Joyent, Inc. 28 */ 29 30 #include <sys/asm_linkage.h> 31 #include <sys/asm_misc.h> 32 33 /* 34 * Implementation as specific by ACPI 3.0 specification 35 * section 5.2.10.1 36 * 37 * Global Lock Structure within the FACS 38 * 39 * |-----------------------------------------------------------------------| 40 * | Field | Bit Length | Bit Offset | Description | 41 * |---------|------------|------------|-----------------------------------| 42 * | Pending | 1 | 0 | Non-zero indicates that a request | 43 * | | | | for ownership of the global lock | 44 * | | | | is pending. | 45 * |---------|------------|------------|-----------------------------------| 46 * | Owned | 1 | 1 | Non-zero indicates that the Global| 47 * | | | | lock is owned. | 48 * |---------|------------|------------|-----------------------------------| 49 * | Reserved| 30 | 2 | Reserved for future use | 50 * |---------|------------|------------|-----------------------------------| 51 */ 52 53 /* Offset of GlobalLock element in FACS structure */ 54 #define GlobalLock 0x10 55 56 ENTRY(__acpi_acquire_global_lock) 57 movq $0xff, %rax / error return if FACS is null 58 orq %rdi, %rdi / %rdi contains pointer to FACS 59 jz 1f 60 leaq GlobalLock(%rdi), %rdi / make %rdi point at the lock 61 0: 62 movl (%rdi), %eax / get current value of Global Lock 63 movl %eax, %edx 64 andl $0xFFFFFFFE, %edx / Clear pending bit 65 btsl $1, %edx / Check and set owner bit 66 adcl $0, %edx / If owned, set pending bit 67 lock 68 cmpxchgl %edx, (%rdi) / Attempt to set new value 69 jnz 0b / If not set, try again 70 cmpb $3, %dl / Was it acquired or marked pending? 71 sbbq %rax, %rax / acquired = -1, pending = 0 72 1: 73 ret 74 SET_SIZE(__acpi_acquire_global_lock) 75 76 77 ENTRY(__acpi_release_global_lock) 78 xorq %rax, %rax / error return if FACS is null 79 orq %rdi, %rdi / %rdi contains pointer to FACS 80 jz 1f 81 leaq GlobalLock(%rdi), %rdi / make %rdi point at the lock 82 0: 83 movl (%rdi), %eax 84 movl %eax, %edx 85 andl $0xFFFFFFFC, %edx 86 lock 87 cmpxchgl %edx, (%rdi) 88 jnz 0b 89 andq $1, %rax 90 1: 91 ret 92 SET_SIZE(__acpi_release_global_lock) 93 94 95 /* 96 * execute WBINVD instruction 97 */ 98 99 ENTRY(__acpi_wbinvd) 100 wbinvd 101 ret 102 SET_SIZE(__acpi_wbinvd) 103