tc_coherence.c
3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
* Copyright (C) 1996-1998 by the Board of Trustees
* of Leland Stanford Junior University.
*
* This file is part of the SimOS distribution.
* See LICENSE file for terms of the license.
*
*/
/****************************************************************
* tc_coherence.c
*
* $Author: blythe $
* $Date: 2002/05/29 01:09:09 $
*****************************************************************/
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include "sim_error.h"
#include "simutil.h"
#include "tc_coherence.h"
#include "machine_params.h"
#include "arch_specifics.h"
#define CHUNK_SIZE (PAGE_SIZE)
#define NORMALIZE(_y) ( (VA)((_y)-tcCohState.start) /CHUNK_SIZE)
#define BYTE_INDEX(_x) (NORMALIZE(_x)>>3)
#define BIT_INDEX(_x) (NORMALIZE(_x) & 0x7)
#define BIT(_x) (1<<(_x))
#define TCCOHERENCE_SIZE(_size) ((_size)/(8*CHUNK_SIZE))
/* Module private Data */
/*XXX- What we want to handle is having a cache line of code */
/*write to itself without having the simulation get into an infinite */
/*flushing loop. Note that such a sequence could not execute itself */
/*without a flush operation before execution of the portion of the */
/*line written. */
/* Unfortunately the boot code written into the first user process */
/* does write into a code line before it calls exec (even though it */
/* doesn't execute this code), so this mechanism must exist */
static struct {
char *bm;
MA start;
MA end;
VA size;
} tcCohState;
#define ICBM(_mAddr) (tcCohState.bm[BYTE_INDEX(_mAddr)])
#define ICBMADDR(_mAddr) (&tcCohStatebm[BYTE_INDEX(_mAddr)])
#define ICBMSET(_mAddr) (tcCohState.bm[BYTE_INDEX(_mAddr)] |= BIT(BIT_INDEX(_mAddr)))
void TCcoherence_init( MA start )
{
VA total =0;
int mach;
for (mach =0; mach < NUM_MACHINES; mach++) {
total += MEM_SIZE(mach);
}
ASSERT(total);
tcCohState.start = start;
tcCohState.end = start + total;
tcCohState.size = TCCOHERENCE_SIZE(total);
tcCohState.bm = ZALLOC_PERM(TCCOHERENCE_SIZE(total),"TCCoherence");
CPUPrint("0x%x D TCCOHERE_BASE 0x%x\n",
tcCohState.bm,
tcCohState.bm+TCCOHERENCE_SIZE(total) );
}
void TCcoherence_flush(void)
{
if (!tcCohState.bm) return;
bzero(tcCohState.bm,tcCohState.size);
}
void TCcoherence_mark_code(MA start, MA finish )
{
MA mAddr;
ASSERT(start < finish);
ASSERT(start >= tcCohState.start);
ASSERT(finish <= tcCohState.end);
for (mAddr=start; mAddr<finish;mAddr +=CHUNK_SIZE) {
ICBMSET(mAddr);
}
}
int TCcoherence_is_code( MA mAddr )
{
if (!tcCohState.bm) return 0;
ASSERT( tcCohState.start <= mAddr);
ASSERT( mAddr < tcCohState.end);
return ICBM(mAddr) & BIT(BIT_INDEX(mAddr));
}
/* vAddr only for debugging output */
/* 0 - return normally, 1 - return via set_pc... */
int TCcoherence_check( MA start, MA finish )
{
MA mAddr;
ASSERT(start < finish);
ASSERT(start >= tcCohState.start);
ASSERT(finish <= tcCohState.end);
for( mAddr = start; mAddr < finish; mAddr += CHUNK_SIZE ) {
if( ICBM(mAddr) & BIT(BIT_INDEX(mAddr)) ) {
CPUPrint("TCcoherence_check. Violation for mAddr=0x%llx finish=0x%llx\n",
(uint64)start,(uint64)finish);
return 1;
}
}
return 0;
}