/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- **************************************************************************** * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge * (C) 2002-2003 - Keir Fraser - University of Cambridge **************************************************************************** * * File: time.c * Author: Rolf Neugebauer and Keir Fraser * * Description: Simple time and timer functions * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include /************************************************************************ * Time functions *************************************************************************/ static unsigned int rdtsc_bitshift; static u32 st_scale_f; /* convert ticks -> usecs */ static u32 st_scale_i; /* convert ticks -> usecs */ /* These are peridically updated in shared_info, and then copied here. */ static u32 shadow_tsc_stamp; static s64 shadow_system_time; static u32 shadow_time_version; static struct timeval shadow_tv; #ifndef rmb #define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory") #endif #define HANDLE_USEC_OVERFLOW(_tv) \ do { \ while ( (_tv).tv_usec >= 1000000 ) \ { \ (_tv).tv_usec -= 1000000; \ (_tv).tv_sec++; \ } \ } while ( 0 ) static void get_time_values_from_xen(void) { do { shadow_time_version = HYPERVISOR_shared_info->time_version2; rmb(); shadow_tv.tv_sec = HYPERVISOR_shared_info->wc_sec; shadow_tv.tv_usec = HYPERVISOR_shared_info->wc_usec; shadow_tsc_stamp = HYPERVISOR_shared_info->tsc_timestamp.tsc_bits; shadow_system_time = HYPERVISOR_shared_info->system_time; rmb(); } while ( shadow_time_version != HYPERVISOR_shared_info->time_version1 ); } #define TIME_VALUES_UP_TO_DATE \ (shadow_time_version == HYPERVISOR_shared_info->time_version2) static __inline__ unsigned long get_time_delta_usecs(void) { s32 delta_tsc; u32 low; u64 delta, tsc; rdtscll(tsc); low = (u32)(tsc >> rdtsc_bitshift); delta_tsc = (s32)(low - shadow_tsc_stamp); if ( unlikely(delta_tsc < 0) ) delta_tsc = 0; delta = ((u64)delta_tsc * st_scale_f); delta >>= 32; delta += ((u64)delta_tsc * st_scale_i); return (unsigned long)delta; } s64 get_s_time (void) { u64 u_delta; s64 ret; again: u_delta = get_time_delta_usecs(); ret = shadow_system_time + (1000 * u_delta); if ( unlikely(!TIME_VALUES_UP_TO_DATE) ) { /* * We may have blocked for a long time, rendering our calculations * invalid (e.g. the time delta may have overflowed). Detect that * and recalculate with fresh values. */ get_time_values_from_xen(); goto again; } return ret; } void gettimeofday(struct timeval *tv) { struct timeval _tv; do { get_time_values_from_xen(); _tv.tv_usec = get_time_delta_usecs(); _tv.tv_sec = shadow_tv.tv_sec; _tv.tv_usec += shadow_tv.tv_usec; } while ( unlikely(!TIME_VALUES_UP_TO_DATE) ); HANDLE_USEC_OVERFLOW(_tv); *tv = _tv; } /* * Just a dummy */ static void timer_handler(int ev, struct pt_regs *regs) { static int i; struct timeval tv; get_time_values_from_xen(); i++; if (i >= 1000) { gettimeofday(&tv); printf("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec); i = 0; } } void init_time(void) { u64 __cpu_khz, cpu_freq, scale; unsigned long cpu_khz; __cpu_khz = HYPERVISOR_shared_info->cpu_freq; cpu_khz = (u32) (__cpu_khz/1000); rdtsc_bitshift = HYPERVISOR_shared_info->tsc_timestamp.tsc_bitshift; cpu_freq = HYPERVISOR_shared_info->cpu_freq; scale = 1000000LL << (32 + rdtsc_bitshift); scale /= cpu_freq; st_scale_f = scale & 0xffffffff; st_scale_i = scale >> 32; printk("Xen reported: %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); add_ev_action(EV_TIMER, &timer_handler); enable_ev_action(EV_TIMER); enable_hypervisor_event(EV_TIMER); } > 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
--  LLVM binding
--  Copyright (C) 2014 Tristan Gingold
--
--  This program is free software: you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation, either version 2 of the License, or
--  (at your option) any later version.
--
--  This program is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU General Public License for more details.
--
--  You should have received a copy of the GNU General Public License
--  along with this program.  If not, see <gnu.org/licenses>.
with System;
with LLVM.Core; use LLVM.Core;
with LLVM.Target; use LLVM.Target;

package LLVM.TargetMachine is

   type TargetMachineRef is new System.Address;
   Null_TargetMachineRef : constant TargetMachineRef :=
     TargetMachineRef (System.Null_Address);

   type TargetRef is new System.Address;
   Null_TargetRef : constant TargetRef := TargetRef (System.Null_Address);

   type CodeGenOptLevel is (CodeGenLevelNone,
                            CodeGenLevelLess,
                            CodeGenLevelDefault,
                            CodeGenLevelAggressive);
   pragma Convention (C, CodeGenOptLevel);

   type RelocMode is (RelocDefault,
                      RelocStatic,
                      RelocPIC,
                      RelocDynamicNoPic);
   pragma Convention (C, RelocMode);

   type CodeModel is (CodeModelDefault,
                      CodeModelJITDefault,
                      CodeModelSmall,
                      CodeModelKernel,
                      CodeModelMedium,
                      CodeModelLarge);
   pragma Convention (C, CodeModel);

   type CodeGenFileType is (AssemblyFile,
                            ObjectFile);
   pragma Convention (C, CodeGenFileType);

   --  Returns the first llvm::Target in the registered targets list.
   function GetFirstTarget return TargetRef;
   pragma Import (C, GetFirstTarget, "LLVMGetFirstTarget");

   --  Returns the next llvm::Target given a previous one (or null if there's
   --  none) */
   function GetNextTarget(T : TargetRef) return TargetRef;
   pragma Import (C, GetNextTarget, "LLVMGetNextTarget");

   --  Target

   --  Finds the target corresponding to the given name and stores it in T.
   --  Returns 0 on success.
   function GetTargetFromName (Name : Cstring) return TargetRef;
   pragma Import (C, GetTargetFromName, "LLVMGetTargetFromName");

   --  Finds the target corresponding to the given triple and stores it in T.
   --  Returns 0 on success. Optionally returns any error in ErrorMessage.
   --  Use LLVMDisposeMessage to dispose the message.
   --  Ada: ErrorMessage is the address of a Cstring.
   function GetTargetFromTriple
     (Triple : Cstring; T : access TargetRef; ErrorMessage : access Cstring)
     return Bool;
   pragma Import (C, GetTargetFromTriple, "LLVMGetTargetFromTriple");

   --  Returns the name of a target. See llvm::Target::getName
   function GetTargetName (T: TargetRef) return Cstring;
   pragma Import (C, GetTargetName, "LLVMGetTargetName");

   --  Returns the description  of a target. See llvm::Target::getDescription
   function GetTargetDescription (T : TargetRef) return Cstring;
   pragma Import (C, GetTargetDescription, "LLVMGetTargetDescription");

   --  Target Machine ----------------------------------------------------

   --  Creates a new llvm::TargetMachine. See llvm::Target::createTargetMachine

   function CreateTargetMachine(T : TargetRef;
                                Triple : Cstring;
                                CPU : Cstring;
                                Features : Cstring;
                                Level : CodeGenOptLevel;
                                Reloc : RelocMode;
                                CM : CodeModel)
                               return TargetMachineRef;
   pragma Import (C, CreateTargetMachine, "LLVMCreateTargetMachine");

   --  Create a DataLayout based on the targetMachine.
   function CreateTargetDataLayout (T : TargetMachineRef) return TargetDataRef;
   pragma Import (C, CreateTargetDataLayout, "LLVMCreateTargetDataLayout");

   -- Returns the llvm::DataLayout used for this llvm:TargetMachine.
   function GetTargetMachineData(T : TargetMachineRef) return TargetDataRef;
   pragma Import (C, GetTargetMachineData, "LLVMGetTargetMachineData");

   --  Emits an asm or object file for the given module to the filename. This
   --  wraps several c++ only classes (among them a file stream). Returns any
   --  error in ErrorMessage. Use LLVMDisposeMessage to dispose the message.
   function TargetMachineEmitToFile(T : TargetMachineRef;
                                    M : ModuleRef;
                                    Filename : Cstring;
                                    Codegen : CodeGenFileType;
                                    ErrorMessage : access Cstring)
                                   return Bool;
   pragma Import (C, TargetMachineEmitToFile,
                  "LLVMTargetMachineEmitToFile");

   --  Get a triple for the host machine as a string. The result needs to be
   --  disposed with LLVMDisposeMessage.
   function GetDefaultTargetTriple return Cstring;
   pragma Import (C, GetDefaultTargetTriple, "LLVMGetDefaultTargetTriple");
end LLVM.TargetMachine;