1/* 2 * Copyright (c) 2004-2012 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * @OSF_COPYRIGHT@ 30 */ 31/* 32 * @APPLE_FREE_COPYRIGHT@ 33 */ 34/* 35 * File: rtclock_asm.h 36 * Purpose: Assembly routines for handling the machine dependent 37 * real-time clock. 38 */ 39 40#ifndef _I386_RTCLOCK_H_ 41#define _I386_RTCLOCK_H_ 42 43#include <i386/pal_rtclock_asm.h> 44 45/* 46 * Nanotime returned in %rax. 47 * Computed from tsc based on the scale factor and an implicit 32 bit shift. 48 * This code must match what _rtc_nanotime_read does in 49 * machine_routines_asm.s. Failure to do so can 50 * result in "weird" timing results. 51 * 52 * Uses: %rsi, %rdi, %rdx, %rcx 53 */ 54#define NANOTIME \ 55 movq %gs:CPU_NANOTIME,%rdi ; \ 56 PAL_RTC_NANOTIME_READ_FAST() 57 58/* 59 * Add 64-bit delta in register reg to timer pointed to by register treg. 60 */ 61#define TIMER_UPDATE(treg,reg,offset) \ 62 addq reg,(offset)+TIMER_ALL(treg) /* add timer */ 63 64/* 65 * Add time delta to old timer and start new. 66 * Uses: %rsi, %rdi, %rdx, %rcx, %rax 67 */ 68#define TIMER_EVENT(old,new) \ 69 NANOTIME /* %rax := nanosecs */ ; \ 70 movq %rax,%rsi /* save timestamp */ ; \ 71 movq %gs:CPU_ACTIVE_THREAD,%rcx /* get thread */ ; \ 72 subq (old##_TIMER)+TIMER_TSTAMP(%rcx),%rax /* compute elapsed */; \ 73 TIMER_UPDATE(%rcx,%rax,old##_TIMER) /* update timer */ ; \ 74 leaq (new##_TIMER)(%rcx),%rcx /* point to new timer */ ; \ 75 movq %rsi,TIMER_TSTAMP(%rcx) /* set timestamp */ ; \ 76 movq %gs:CPU_PROCESSOR,%rdx /* get processor */ ; \ 77 movq %rcx,THREAD_TIMER(%rdx) /* set current timer */ ; \ 78 movq %rsi,%rax /* restore timestamp */ ; \ 79 subq (old##_STATE)+TIMER_TSTAMP(%rdx),%rax /* compute elapsed */; \ 80 TIMER_UPDATE(%rdx,%rax,old##_STATE) /* update timer */ ; \ 81 leaq (new##_STATE)(%rdx),%rcx /* point to new state */ ; \ 82 movq %rcx,CURRENT_STATE(%rdx) /* set current state */ ; \ 83 movq %rsi,TIMER_TSTAMP(%rcx) /* set timestamp */ 84 85/* 86 * Update time on user trap entry. 87 * Uses: %rsi, %rdi, %rdx, %rcx, %rax 88 */ 89#define TIME_TRAP_UENTRY TIMER_EVENT(USER,SYSTEM) 90 91/* 92 * update time on user trap exit. 93 * Uses: %rsi, %rdi, %rdx, %rcx, %rax 94 */ 95#define TIME_TRAP_UEXIT TIMER_EVENT(SYSTEM,USER) 96 97/* 98 * update time on interrupt entry. 99 * Uses: %rsi, %rdi, %rdx, %rcx, %rax 100 * Saves processor state info on stack. 101 */ 102#define TIME_INT_ENTRY \ 103 NANOTIME /* %rax := nanosecs */ ; \ 104 movq %rax,%gs:CPU_INT_EVENT_TIME /* save in cpu data */ ; \ 105 movq %rax,%rsi /* save timestamp */ ; \ 106 movq %gs:CPU_PROCESSOR,%rdx /* get processor */ ; \ 107 movq THREAD_TIMER(%rdx),%rcx /* get current timer */ ; \ 108 subq TIMER_TSTAMP(%rcx),%rax /* compute elapsed */ ; \ 109 TIMER_UPDATE(%rcx,%rax,0) /* update timer */ ; \ 110 movq KERNEL_TIMER(%rdx),%rcx /* get kernel timer */ ; \ 111 movq %rsi,TIMER_TSTAMP(%rcx) /* set timestamp */ ; \ 112 movq %rsi,%rax /* restore timestamp */ ; \ 113 movq CURRENT_STATE(%rdx),%rcx /* get current state */ ; \ 114 pushq %rcx /* save state */ ; \ 115 subq TIMER_TSTAMP(%rcx),%rax /* compute elapsed */ ; \ 116 TIMER_UPDATE(%rcx,%rax,0) /* update timer */ ; \ 117 leaq IDLE_STATE(%rdx),%rax /* get idle state */ ; \ 118 cmpq %rax,%rcx /* compare current */ ; \ 119 je 0f /* skip if equal */ ; \ 120 leaq SYSTEM_STATE(%rdx),%rcx /* get system state */ ; \ 121 movq %rcx,CURRENT_STATE(%rdx) /* set current state */ ; \ 1220: movq %rsi,TIMER_TSTAMP(%rcx) /* set timestamp */ 123 124/* 125 * update time on interrupt exit. 126 * Uses: %rsi, %rdi, %rdx, %rcx, %rax 127 * Restores processor state info from stack. 128 */ 129#define TIME_INT_EXIT \ 130 NANOTIME /* %rax := nanosecs */ ; \ 131 movq %rax,%gs:CPU_INT_EVENT_TIME /* save in cpu data */ ; \ 132 movq %rax,%rsi /* save timestamp */ ; \ 133 movq %gs:CPU_PROCESSOR,%rdx /* get processor */ ; \ 134 movq KERNEL_TIMER(%rdx),%rcx /* get kernel timer */ ; \ 135 subq TIMER_TSTAMP(%rcx),%rax /* compute elapsed */ ; \ 136 TIMER_UPDATE(%rcx,%rax,0) /* update timer */ ; \ 137 movq THREAD_TIMER(%rdx),%rcx /* interrupted timer */ ; \ 138 movq %rsi,TIMER_TSTAMP(%rcx) /* set timestamp */ ; \ 139 movq %rsi,%rax /* restore timestamp */ ; \ 140 movq CURRENT_STATE(%rdx),%rcx /* get current state */ ; \ 141 subq TIMER_TSTAMP(%rcx),%rax /* compute elapsed */ ; \ 142 TIMER_UPDATE(%rcx,%rax,0) /* update timer */ ; \ 143 popq %rcx /* restore state */ ; \ 144 movq %rcx,CURRENT_STATE(%rdx) /* set current state */ ; \ 145 movq %rsi,TIMER_TSTAMP(%rcx) /* set timestamp */ 146 147 148/* 149 * Check for vtimers for task. 150 * task_reg is register pointing to current task 151 * thread_reg is register pointing to current thread 152 */ 153#define TASK_VTIMER_CHECK(task_reg,thread_reg) \ 154 cmpl $0,TASK_VTIMERS(task_reg) ; \ 155 jz 1f ; \ 156 orl $(AST_BSD),%gs:CPU_PENDING_AST /* Set pending AST */ ; \ 157 lock ; \ 158 orl $(AST_BSD),TH_AST(thread_reg) /* Set thread AST */ ; \ 1591: ; \ 160 161#endif /* _I386_RTCLOCK_H_ */ 162