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