1963Ssaidi@eecs.umich.edu/* 2963Ssaidi@eecs.umich.edu * Copyright (c) 2004 The Regents of The University of Michigan 3963Ssaidi@eecs.umich.edu * All rights reserved. 4963Ssaidi@eecs.umich.edu * 5963Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 6963Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are 7963Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright 8963Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 9963Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 10963Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 11963Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution; 12963Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its 13963Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from 14963Ssaidi@eecs.umich.edu * this software without specific prior written permission. 15963Ssaidi@eecs.umich.edu * 16963Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17963Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18963Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19963Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20963Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21963Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22963Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23963Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24963Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25963Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26963Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Ali Saidi 29963Ssaidi@eecs.umich.edu */ 30963Ssaidi@eecs.umich.edu 31963Ssaidi@eecs.umich.edu#include <asm/io.h> 32964Ssaidi@eecs.umich.edu#include <asm/page.h> 338229Snate@binkert.org#include <asm/uaccess.h> 348229Snate@binkert.org#include <linux/config.h> 358229Snate@binkert.org#include <linux/fs.h> 368229Snate@binkert.org#include <linux/init.h> 378229Snate@binkert.org#include <linux/kernel.h> 388229Snate@binkert.org#include <linux/module.h> 398229Snate@binkert.org#include <linux/moduleparam.h> 40963Ssaidi@eecs.umich.edu#include <linux/netdevice.h> 41963Ssaidi@eecs.umich.edu 42963Ssaidi@eecs.umich.edu#ifdef __i386__ 438229Snate@binkert.org#include <asm/msr.h> 44963Ssaidi@eecs.umich.edu#include <asm/processor.h> 45963Ssaidi@eecs.umich.edu#endif 46963Ssaidi@eecs.umich.edu 47963Ssaidi@eecs.umich.edu#define DRIVER_AUTHOR "Ali Saidi" 48963Ssaidi@eecs.umich.edu#define DRIVER_DESC "Interface to time uncacachable read and writes to device registers" 49963Ssaidi@eecs.umich.edu#define DRIVER_VER "0.1" 50963Ssaidi@eecs.umich.edu 51963Ssaidi@eecs.umich.edustatic char *dataAddr = NULL; 52963Ssaidi@eecs.umich.edustatic int count = 0; 531068Ssaidi@eecs.umich.edu#ifdef __alpha__ 541068Ssaidi@eecs.umich.edustatic int memTest = 0; 551068Ssaidi@eecs.umich.edu#endif 56963Ssaidi@eecs.umich.edu 57963Ssaidi@eecs.umich.edustatic inline uint32_t cycleCounter(uint32_t dep); 58963Ssaidi@eecs.umich.edu 59963Ssaidi@eecs.umich.edustatic int __init devtime_start(void) 60963Ssaidi@eecs.umich.edu{ 61963Ssaidi@eecs.umich.edu uint64_t addr; 62996Sbinkertn@umich.edu uint32_t t1, t2; 63963Ssaidi@eecs.umich.edu uint32_t trash; 64963Ssaidi@eecs.umich.edu int x; 651051Ssaidi@eecs.umich.edu uint32_t *times; 661051Ssaidi@eecs.umich.edu uint32_t num = 0; 67963Ssaidi@eecs.umich.edu struct net_device *dev; 68963Ssaidi@eecs.umich.edu 69963Ssaidi@eecs.umich.edu printk("Devtime Driver Version %s Loaded...\n", DRIVER_VER); 70963Ssaidi@eecs.umich.edu 711068Ssaidi@eecs.umich.edu#ifdef __alpha__ 721068Ssaidi@eecs.umich.edu if (memTest) { 731068Ssaidi@eecs.umich.edu addr = 0xfffffc0000000000; 741068Ssaidi@eecs.umich.edu// addr += 16*1024*1024; 751068Ssaidi@eecs.umich.edu 761068Ssaidi@eecs.umich.edu printk("Preparing memory test.\n"); 771068Ssaidi@eecs.umich.edu 781068Ssaidi@eecs.umich.edu t1 = cycleCounter(trash); 791068Ssaidi@eecs.umich.edu for (x = 0; x < count; x++) { 801068Ssaidi@eecs.umich.edu trash = readl(addr); 811068Ssaidi@eecs.umich.edu t2 = cycleCounter(trash); 821068Ssaidi@eecs.umich.edu times[num++] = t2 - t1; 831068Ssaidi@eecs.umich.edu t1 = t2; 841068Ssaidi@eecs.umich.edu addr += 4096; 851068Ssaidi@eecs.umich.edu } 861068Ssaidi@eecs.umich.edu 871068Ssaidi@eecs.umich.edu printk("Measurements:\n"); 881068Ssaidi@eecs.umich.edu for (x = 0; x < count; x++) { 891068Ssaidi@eecs.umich.edu printk("%d ", times[x]); 901068Ssaidi@eecs.umich.edu if (((x + 1) % 10) == 0) 911068Ssaidi@eecs.umich.edu printk("\n"); 921068Ssaidi@eecs.umich.edu } 931068Ssaidi@eecs.umich.edu printk("\nDone.\n"); 941068Ssaidi@eecs.umich.edu } else 951068Ssaidi@eecs.umich.edu#endif 96996Sbinkertn@umich.edu if (dataAddr != 0 && count != 0) { 97963Ssaidi@eecs.umich.edu addr = simple_strtoull(dataAddr, NULL, 0); 98963Ssaidi@eecs.umich.edu 99964Ssaidi@eecs.umich.edu addr = ioremap(addr, PAGE_SIZE); 100964Ssaidi@eecs.umich.edu /** 101964Ssaidi@eecs.umich.edu * Make sure that the remapping actually worked. On alpha we have 102964Ssaidi@eecs.umich.edu * linear addressing, so its not a problem. But it can fail in x86 103964Ssaidi@eecs.umich.edu * if physical memory is mapped to this address. 104964Ssaidi@eecs.umich.edu */ 1051051Ssaidi@eecs.umich.edu times = kmalloc(sizeof(uint32_t) * count, GFP_USER); 106996Sbinkertn@umich.edu if (!times) { 1071051Ssaidi@eecs.umich.edu printk("Could not allocate memory... Try again later.\n"); 1081051Ssaidi@eecs.umich.edu return -1; 1091051Ssaidi@eecs.umich.edu } 1101051Ssaidi@eecs.umich.edu 111996Sbinkertn@umich.edu if (addr) { 112964Ssaidi@eecs.umich.edu printk("Preparing to read %#llx %d times.\n", addr, count); 113963Ssaidi@eecs.umich.edu 114964Ssaidi@eecs.umich.edu t1 = cycleCounter(trash); 115996Sbinkertn@umich.edu for (x = 0; x < count; x++) { 116964Ssaidi@eecs.umich.edu trash = readl(addr); 117964Ssaidi@eecs.umich.edu t2 = cycleCounter(trash); 1181051Ssaidi@eecs.umich.edu times[num++] = t2 - t1; 119964Ssaidi@eecs.umich.edu t1 = t2; 120964Ssaidi@eecs.umich.edu } 121964Ssaidi@eecs.umich.edu 122964Ssaidi@eecs.umich.edu /** 123964Ssaidi@eecs.umich.edu * Unmap the address. 124964Ssaidi@eecs.umich.edu */ 125964Ssaidi@eecs.umich.edu iounmap(addr); 126964Ssaidi@eecs.umich.edu 1271051Ssaidi@eecs.umich.edu printk("Measurements:\n"); 128996Sbinkertn@umich.edu for (x = 0; x < count; x++) { 1291051Ssaidi@eecs.umich.edu printk("%d ", times[x]); 130996Sbinkertn@umich.edu if (((x + 1) % 10) == 0) 1311051Ssaidi@eecs.umich.edu printk("\n"); 1321051Ssaidi@eecs.umich.edu } 1331051Ssaidi@eecs.umich.edu printk("\nDone.\n"); 134996Sbinkertn@umich.edu } else { 135996Sbinkertn@umich.edu printk("Unable to remap address. Please try again later.\n"); 136963Ssaidi@eecs.umich.edu } 137963Ssaidi@eecs.umich.edu } else { 138963Ssaidi@eecs.umich.edu dev = dev_get_by_name("eth0"); 139996Sbinkertn@umich.edu if (dev) { 140996Sbinkertn@umich.edu printk("Eth0: MemStart: %#lx MemEnd: %#lx I/O Addr: %#lx\n", 141996Sbinkertn@umich.edu dev->mem_start, dev->mem_end, dev->base_addr); 142963Ssaidi@eecs.umich.edu dev_put(dev); 143963Ssaidi@eecs.umich.edu } 144964Ssaidi@eecs.umich.edu dev = 0; 145963Ssaidi@eecs.umich.edu dev = dev_get_by_name("eth1"); 146996Sbinkertn@umich.edu if (dev) { 147996Sbinkertn@umich.edu printk("Eth1: MemStart: %#lx MemEnd: %#lx I/O Addr: %#lx\n", 148996Sbinkertn@umich.edu dev->mem_start, dev->mem_end, dev->base_addr); 149963Ssaidi@eecs.umich.edu dev_put(dev); 150963Ssaidi@eecs.umich.edu } 151963Ssaidi@eecs.umich.edu 152963Ssaidi@eecs.umich.edu printk("Required information not supplied.\n"); 153963Ssaidi@eecs.umich.edu } 154963Ssaidi@eecs.umich.edu 155963Ssaidi@eecs.umich.edu return 0; 156963Ssaidi@eecs.umich.edu} 157963Ssaidi@eecs.umich.edu 158963Ssaidi@eecs.umich.edu#ifdef __i386__ 159963Ssaidi@eecs.umich.edu 160963Ssaidi@eecs.umich.edustatic inline uint32_t cycleCounter(uint32_t dep) 161963Ssaidi@eecs.umich.edu{ 162963Ssaidi@eecs.umich.edu uint32_t time; 163963Ssaidi@eecs.umich.edu cpuid_eax(0); 164963Ssaidi@eecs.umich.edu rdtscl(time); 165963Ssaidi@eecs.umich.edu cpuid_eax(0); 166963Ssaidi@eecs.umich.edu return time; 167963Ssaidi@eecs.umich.edu} 168963Ssaidi@eecs.umich.edu 169963Ssaidi@eecs.umich.edu#elif __alpha__ 170963Ssaidi@eecs.umich.edu 171963Ssaidi@eecs.umich.eduinline uint32_t cycleCounter(uint32_t dep) 172963Ssaidi@eecs.umich.edu{ 173963Ssaidi@eecs.umich.edu uint32_t res; 174963Ssaidi@eecs.umich.edu asm volatile ("rpcc %0, %1" : "=r"(res) : "r" (dep) : "memory"); 175963Ssaidi@eecs.umich.edu return res; 176963Ssaidi@eecs.umich.edu} 177963Ssaidi@eecs.umich.edu#else 1781068Ssaidi@eecs.umich.edu#error Architecture NOT SUPPORTED 179963Ssaidi@eecs.umich.edu#endif 180963Ssaidi@eecs.umich.edu 181996Sbinkertn@umich.edustatic void __exit devtime_end(void) 182996Sbinkertn@umich.edu{ 183963Ssaidi@eecs.umich.edu printk("Devtime Driver Version %s Unloaded...\n", DRIVER_VER); 184963Ssaidi@eecs.umich.edu} 185963Ssaidi@eecs.umich.edu 186963Ssaidi@eecs.umich.edu 187963Ssaidi@eecs.umich.edumodule_init(devtime_start); 188963Ssaidi@eecs.umich.edumodule_exit(devtime_end); 189963Ssaidi@eecs.umich.edu 1901051Ssaidi@eecs.umich.eduMODULE_LICENSE("Dual BSD/GPL"); 191963Ssaidi@eecs.umich.eduMODULE_AUTHOR(DRIVER_AUTHOR); 192963Ssaidi@eecs.umich.eduMODULE_DESCRIPTION(DRIVER_DESC); 193963Ssaidi@eecs.umich.edumodule_param(dataAddr, charp, 0); 194963Ssaidi@eecs.umich.edumodule_param(count, int, 0); 1951068Ssaidi@eecs.umich.edu#ifdef __alpha__ 1961068Ssaidi@eecs.umich.edumodule_param(memTest, int, 0); 1971068Ssaidi@eecs.umich.edu#endif 198