diff --git a/sys/amd64/include/acpica_machdep.h b/sys/amd64/include/acpica_machdep.h index ea501feaa724..07029e1037ce 100644 --- a/sys/amd64/include/acpica_machdep.h +++ b/sys/amd64/include/acpica_machdep.h @@ -59,44 +59,14 @@ #define ACPI_FLUSH_CPU_CACHE() wbinvd() -#define asm __asm -/*! [Begin] no source code translation - * - * A brief explanation as GNU inline assembly is a bit hairy - * %0 is the output parameter in EAX ("=a") - * %1 and %2 are the input parameters in ECX ("c") - * and an immediate value ("i") respectively - * All actual register references are preceded with "%%" as in "%%edx" - * Immediate values in the assembly are preceded by "$" as in "$0x1" - * The final asm parameter are the operation altered non-output registers. - */ +/* Section 5.2.9.1: global lock acquire/release functions */ +extern int acpi_acquire_global_lock(uint32_t *lock); +extern int acpi_release_global_lock(uint32_t *lock); #define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - asm("1: movl %1,%%eax;" \ - "movl %%eax,%%edx;" \ - "andl %2,%%edx;" \ - "btsl $0x1,%%edx;" \ - "adcl $0x0,%%edx;" \ - "lock; cmpxchgl %%edx,%1;" \ - "jnz 1b;" \ - "cmpb $0x3,%%dl;" \ - "sbbl %%eax,%%eax" \ - : "=a" (Acq), "+m" (GLptr) : "i" (~1L) : "edx"); \ - } while(0) - + ((Acq) = acpi_acquire_global_lock(GLptr)) #define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - asm("1: movl %1,%%eax;" \ - "movl %%eax,%%edx;" \ - "andl %2,%%edx;" \ - "lock; cmpxchgl %%edx,%1;" \ - "jnz 1b;" \ - "andl $0x1,%%eax" \ - : "=a" (Acq), "+m" (GLptr) : "i" (~3L) : "edx"); \ - } while(0) - - -/*! [End] no source code translation !*/ + ((Acq) = acpi_release_global_lock(GLptr)) + #endif /* _KERNEL */ #define ACPI_MACHINE_WIDTH 64 diff --git a/sys/dev/acpica/Osd/OsdSynch.c b/sys/dev/acpica/Osd/OsdSynch.c index 5f3398e20a32..34b66fda394a 100644 --- a/sys/dev/acpica/Osd/OsdSynch.c +++ b/sys/dev/acpica/Osd/OsdSynch.c @@ -389,3 +389,47 @@ AcpiOsReleaseLock (ACPI_HANDLE Handle, UINT32 Flags) return; mtx_unlock(m); } + +/* Section 5.2.9.1: global lock acquire/release functions */ +#define GL_ACQUIRED (-1) +#define GL_BUSY 0 +#define GL_BIT_PENDING 0x1 +#define GL_BIT_OWNED 0x2 +#define GL_BIT_MASK (GL_BIT_PENDING | GL_BIT_OWNED) + +/* + * Acquire the global lock. If busy, set the pending bit. The caller + * will wait for notification from the BIOS that the lock is available + * and then attempt to acquire it again. + */ +int +acpi_acquire_global_lock(uint32_t *lock) +{ + uint32_t new, old; + + do { + old = *lock; + new = (((old & ~GL_BIT_MASK) | GL_BIT_OWNED) | + ((old >> 1) & GL_BIT_PENDING)); + } while (atomic_cmpset_acq_int(lock, old, new) == 0); + + return ((new < GL_BIT_MASK) ? GL_ACQUIRED : GL_BUSY); +} + +/* + * Release the global lock, returning whether there is a waiter pending. + * If the BIOS set the pending bit, OSPM must notify the BIOS when it + * releases the lock. + */ +int +acpi_release_global_lock(uint32_t *lock) +{ + uint32_t new, old; + + do { + old = *lock; + new = old & ~GL_BIT_MASK; + } while (atomic_cmpset_rel_int(lock, old, new) == 0); + + return (old & GL_BIT_PENDING); +} diff --git a/sys/i386/include/acpica_machdep.h b/sys/i386/include/acpica_machdep.h index 6ff98d8ba724..4eff57d08f77 100644 --- a/sys/i386/include/acpica_machdep.h +++ b/sys/i386/include/acpica_machdep.h @@ -59,46 +59,19 @@ #define ACPI_FLUSH_CPU_CACHE() wbinvd() -#define asm __asm +/* Section 5.2.9.1: global lock acquire/release functions */ +extern int acpi_acquire_global_lock(uint32_t *lock); +extern int acpi_release_global_lock(uint32_t *lock); +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ + ((Acq) = acpi_acquire_global_lock(GLptr)) +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ + ((Acq) = acpi_release_global_lock(GLptr)) + /*! [Begin] no source code translation * - * A brief explanation as GNU inline assembly is a bit hairy - * %0 is the output parameter in EAX ("=a") - * %1 and %2 are the input parameters in ECX ("c") - * and an immediate value ("i") respectively - * All actual register references are preceded with "%%" as in "%%edx" - * Immediate values in the assembly are preceded by "$" as in "$0x1" - * The final asm parameter are the operation altered non-output registers. - */ -#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - asm("1: movl %1,%%eax;" \ - "movl %%eax,%%edx;" \ - "andl %2,%%edx;" \ - "btsl $0x1,%%edx;" \ - "adcl $0x0,%%edx;" \ - "lock; cmpxchgl %%edx,%1;" \ - "jnz 1b;" \ - "cmpb $0x3,%%dl;" \ - "sbbl %%eax,%%eax" \ - : "=a" (Acq), "+m" (GLptr) : "i" (~1L) : "edx"); \ - } while(0) - -#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - asm("1: movl %1,%%eax;" \ - "movl %%eax,%%edx;" \ - "andl %2,%%edx;" \ - "lock; cmpxchgl %%edx,%1;" \ - "jnz 1b;" \ - "andl $0x1,%%eax" \ - : "=a" (Acq), "+m" (GLptr) : "i" (~3L) : "edx"); \ - } while(0) - - -/* * Math helper asm macros */ +#define asm __asm #define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) \ asm("divl %2;" \ :"=a"(q32), "=d"(r32) \ diff --git a/sys/ia64/include/acpica_machdep.h b/sys/ia64/include/acpica_machdep.h index f459b6ae3fcc..315476b0a859 100644 --- a/sys/ia64/include/acpica_machdep.h +++ b/sys/ia64/include/acpica_machdep.h @@ -61,50 +61,13 @@ #define ACPI_FLUSH_CPU_CACHE() /* XXX ia64_fc()? */ -/*! [Begin] no source code translation */ - +/* Section 5.2.9.1: global lock acquire/release functions */ +extern int acpi_acquire_global_lock(uint32_t *lock); +extern int acpi_release_global_lock(uint32_t *lock); #define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - __asm__ volatile ("1: ld4 r29=[%1]\n" \ - ";;\n" \ - "mov ar.ccv=r29\n" \ - "mov r2=r29\n" \ - "shr.u r30=r29,1\n" \ - "and r29=-4,r29\n" \ - ";;\n" \ - "add r29=2,r29\n" \ - "and r30=1,r30\n" \ - ";;\n" \ - "add r29=r29,r30\n" \ - ";;\n" \ - "cmpxchg4.acq r30=[%1],r29,ar.ccv\n" \ - ";;\n" \ - "cmp.eq p6,p7=r2,r30\n" \ - "(p7) br.dpnt.few 1b\n" \ - "cmp.gt p8,p9=3,r29\n" \ - ";;\n" \ - "(p8) mov %0=-1\n" \ - "(p9) mov %0=r0\n" \ - :"=r"(Acq):"r"(GLptr):"r2","r29","r30","memory"); \ - } while (0) - + ((Acq) = acpi_acquire_global_lock(GLptr)) #define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - __asm__ volatile ("1: ld4 r29=[%1]\n" \ - ";;\n" \ - "mov ar.ccv=r29\n" \ - "mov r2=r29\n" \ - "and r29=-4,r29\n" \ - ";;\n" \ - "cmpxchg4.acq r30=[%1],r29,ar.ccv\n" \ - ";;\n" \ - "cmp.eq p6,p7=r2,r30\n" \ - "(p7) br.dpnt.few 1b\n" \ - "and %0=1,r2\n" \ - ";;\n" \ - :"=r"(Acq):"r"(GLptr):"r2","r29","r30","memory"); \ - } while (0) -/*! [End] no source code translation !*/ + ((Acq) = acpi_release_global_lock(GLptr)) #endif /* _KERNEL */