cpu_interface.c
4.19 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.
*
*/
/*****************************************************************
* cpu_interface.c
*****************************************************************/
#include "mips_arch.h"
#include "simtypes.h"
#include "cpu_interface.h"
#include "cpu.h"
#include "mipsy.h"
#include "checkpoint.h"
#include "addr_layout.h"
#include "cp0.h"
#include "tcl_init.h"
#include "machine_params.h"
#include "memif.h"
#include "scache.h"
extern void HandleDebugSignal(int cpuid, int sigusr); /* Defined in debug.c */
extern Result MipsyGetReg(int cpunum, int regnum, Reg *val);
extern Result MipsyPutReg(int cpunum, int regnum, Reg val);
extern Result MipsyGetMem(int cpunum, VA vAddr, uint nbytes, char *buf);
extern Result MipsyPutMem(int cpunum, VA vAddr, uint nbytes, char *buf);
extern Result MipsyTranslateVirtualNoSE(int cpunum, VA vAddr, PA *pAddr);
extern CPUStatus MipsyCPUStatus(int);
static void MipsyDoCheckpoint(int cpuNum);
bool tookCheckpoint = FALSE;
static void
MipsyDMAInval(int machine, PA* k0list)
{
/* the memory system handles cache coherence for DMA, so this routine
is a nop for mipsy */
}
extern void MipsyFinishMemRequests(void);
void
MipsyDoCheckpoint(int cpuNum)
{
#ifndef SOLO
int i;
MipsyFinishMemRequests();
#ifdef DATA_HANDLING
/* if running with DH on, we MUST flush all caches
* before taking the checkpoint.
*/
for (i = 0; i < TOTAL_CPUS; i++) {
FlushEntireCache(i, TRUE);
}
#endif
/* This fixes the problem that arrived when we went to Post-PC
annotations. The PC that the checkpoint annotation was set on
would be the first one to execute when the checkpoint was
restored, thus executing it twice... that's bad.
*/
for (i=0; i < TOTAL_CPUS; i++) {
CPUState *P = &PE[i];
if (AnnFMLookup(P->PC, ANNFM_PC_TYPE)) {
CPUWarning("MIPSY: Checkpoint from post-pc ann %#x on cpu %d\n",
P->PC, i);
/* BAD HACK: The main loop checks this to see if it should
move forward the PC since we need it to move forward
before the checkpoint is taken. */
tookCheckpoint = TRUE;
P->PC = P->nPC;
if (P->branchStatus == BranchStatus_taken) {
P->nPC = P->branchTarget;
P->branchStatus = BranchStatus_nottaken;
} else {
P->nPC += INST_SIZE;
}
CPUWarning("MIPSY: changed PC to %#x\n", P->PC);
}
}
Simcpt_Checkpoint(CPT_SAVE, NULL);
#endif
}
VA
MipsyCurrentPC(int cpu)
{
return pePtr[cpu]->PC;
}
char *
MipsyPAToHostAddr(int cpu, PA pAddr, VA vAddr)
{
#ifdef SOLO
return (char *)(vAddr);
#else
return (PHYS_TO_MEMADDR(M_FROM_CPU(cpu),pAddr) +
(IS_REMAPPED_PADDR(pAddr,cpu) ? remapVec->NodeAddr[cpu] : 0));
#endif
}
/*****************************************************************
* CPUVectorInit
*****************************************************************/
void
CPUVectorInit(void)
{
CPUVec.Handle_Debug_Signal = HandleDebugSignal;
CPUVec.GetRegister = MipsyGetReg;
CPUVec.PutRegister = MipsyPutReg;
CPUVec.GetMemory = MipsyGetMem;
CPUVec.PutMemory = MipsyPutMem;
CPUVec.TranslateVirtualNoSE = MipsyTranslateVirtualNoSE;
CPUVec.Unstall = MipsyUnstall;
CPUVec.CycleCount = MipsyCycleCount;
CPUVec.DMAInval = MipsyDMAInval;
CPUVec.CurrentCpuNum = MipsyCurrentCpuNum;
CPUVec.CurrentPC = MipsyCurrentPC;
CPUVec.InstrCount = MipsyInstructionCount;
CPUVec.DoCheckpoint = MipsyDoCheckpoint;
CPUVec.InstallMemAnnotation = MipsyInstallMemAnnotation;
CPUVec.TakeBusError = MipsyTakeBusError;
CPUVec.useMemRef = TRUE;
CPUVec.PAToHostAddr = MipsyPAToHostAddr;
CPUVec.ReissueUncachedOp = MipsyReissueUncachedOp;
CPUVec.ClearLockFlag = MipsyClearLockFlag;
CPUVec.GetLockFlag = MipsyGetLockFlag;
CPUVec.GetLockAddr = MipsyGetLockAddr;
CPUVec.CPUstatus = MipsyCPUStatus;
}