]> Joshua Wise's Git repositories - netwatch.git/blob - netwatch/smi.c
Add TSC checks to measure how much time we spend in SMM.
[netwatch.git] / netwatch / smi.c
1 /* smi.c
2  * First-run SMI C entry point
3  * NetWatch system management mode administration console
4  *
5  * Copyright (c) 2008 Jacob Potter and Joshua Wise.  All rights reserved.
6  * This program is free software; you can redistribute and/or modify it under
7  * the terms found in the file LICENSE in the root of this source tree.
8  *
9  */
10
11 #include <io.h>
12 #include <smram.h>
13 #include <video_defines.h>
14 #include <minilib.h>
15 #include <smi.h>
16 #include <pci-bother.h>
17 #include <serial.h>
18 #include <fb.h>
19 #include <output.h>
20 #include <msr.h>
21 #include "../net/net.h"
22 #include "vga-overlay.h"
23
24 unsigned int counter = 0;
25 unsigned long pcisave = 0;
26 unsigned char vgasave = 0;
27
28 unsigned long lastentry = 0;
29 unsigned long lastlength = 0;
30
31 unsigned long rdtsc()
32 {
33         unsigned long tsc;
34         asm volatile ("mov %%cr4, %%eax;"
35              "and $~2, %%eax;"
36              "mov %%eax, %%cr4;"
37              "rdtsc" : "=a"(tsc) : : "edx");
38         return tsc;
39 }
40
41 void smi_entry(void)
42 {
43         char statstr[512];
44         unsigned long entrytime;
45
46         /* Reenable caching on SMRAM. */
47         WRMSR(0x202, (RDMSR(0x202) & ~(0xFFULL)) | 0x06ULL);
48
49         entrytime = rdtsc();
50
51         pcisave = inl(0xCF8);
52         vgasave = inb(0x3D4);
53         pci_unbother_all();
54         
55         serial_init();
56
57         if (fb)
58                 fb->getvmode(fb->priv);
59
60         counter++;
61         if (!fb || fb->curmode.text)
62         {
63                 int totcyc, pct;
64                 
65                 if (entrytime < lastentry)
66                         totcyc = entrytime + (0xFFFFFFFFUL - lastentry) + 1;
67                 else
68                         totcyc = entrytime - lastentry;
69                 if (totcyc == 0)
70                         totcyc = 1;     /* argh */
71                 totcyc /= 1000;
72                 if (totcyc == 0)
73                         totcyc = 1;
74                 
75                 pct = lastlength / totcyc;
76                 
77                 sprintf(statstr, "NetWatch! %08x %08x, %2d.%d%%", smi_status(), counter, pct/10, pct%10);
78                 strblit(statstr, 0, 0, 0);
79         }
80         
81         eth_poll();
82         
83         if (inl(0x840) & 0x1000)
84         {
85         /*
86                 pci_dump();
87         */
88                 outl(0x840, 0x1100);
89                 outl(0x840, 0x0100);
90         }
91
92
93         smi_poll();
94         
95         pci_bother_all();
96         outl(0xCF8, pcisave);
97         outb(0x3D4, vgasave);
98         
99         lastentry = entrytime;
100         entrytime = rdtsc();
101         if (entrytime < lastentry)
102                 lastlength = entrytime + (0xFFFFFFFFUL - lastentry) + 1;
103         else
104                 lastlength = entrytime - lastentry;
105         
106         /* Disable caching on SMRAM again, to prevent the user from whacking us. */
107         WRMSR(0x202, RDMSR(0x202) & ~(0xFFULL));
108 }
109
110 extern void timer_handler(smi_event_t ev);
111 extern void kbc_handler(smi_event_t ev);
112 extern void gbl_rls_handler(smi_event_t ev);
113
114 void __firstrun_stub()
115 {
116         /* Turn on the SMIs we want */
117         smi_disable();
118
119         smi_register_handler(SMI_EVENT_FAST_TIMER, timer_handler);
120         smi_enable_event(SMI_EVENT_FAST_TIMER);
121
122         smi_register_handler(SMI_EVENT_DEVTRAP_KBC, kbc_handler);
123         smi_enable_event(SMI_EVENT_DEVTRAP_KBC);
124
125         smi_register_handler(SMI_EVENT_GBL_RLS, gbl_rls_handler);
126         smi_enable_event(SMI_EVENT_GBL_RLS);
127
128         smi_enable();
129 }
This page took 0.035709 seconds and 4 git commands to generate.