📄 firewall.c
字号:
/* * 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. * *//***************************************************************** * firewall.c * *****************************************************************/#include "syslimits.h"#include "simtypes.h"#include "hd.h"#include "checkpoint.h"#include "machine_params.h"#include "cpu_interface.h"#include "cpu_state.h"#include "sim_error.h"#include "addr_layout.h"#include "simutil.h"#include "../../memsystems/flashlite/flash_interface.h"#include "firewall.h"static CptCallback FirewallCheckpointCB;static uint64* fwall[SIM_MAXCPUS]; /* one array allocated for each node */static uint fwn; /* number of nodes */static uint ppn; /* pages per node */static uint ppcell; /* pages per cell */static uint cpus_per_cell_mask; /* unary of cpus per cell */extern CptVersion cptVersion;/* access functions to fwall array entries */#define FW_ISWR(val, cell) (((val) & ((uint64)1 << cell)) != (uint64)0)#define FW_SETWR(val, cell) ((val) | ((uint64)1 << cell))#define FW_CLRWR(val, cell) ((val) & ~((uint64)1 << cell))/* fast case optimization: power-of-two pages per node, < 32 cells */#define FW_ISWR32(val, cell) ((((uint) val) & (1 << cell)) != 0)static uint log2ppcell;static uint log2ppn;static uint ppnodemask;/* function pointer derefed by caller distinguishes fast and slow cases *//* switch for whether to call firewall code */static uint firewall_enabled_flag;uint64sim_firewall_page_prot(int n, int pg){ ASSERT(0 <= n && n < fwn && 0 <= pg && pg < ppn); return fwall[n][pg];}voidsim_firewall_set_page_prot_raw(int n, int pgoffs, uint64 prot){ ASSERT(0 <= n && n < fwn && 0 <= pgoffs && pgoffs < ppn); fwall[n][pgoffs] = prot;}intsim_firewall_set_page_prot(int cpu, int n, int pgoffs, uint64 prot){ uint cellnum = cpu >> log2CPUS_PER_CELL(0); uint pgcell = n >> log2CPUS_PER_CELL(0); ASSERT(0 <= n && n < fwn && 0 <= pgoffs && pgoffs < ppn); ASSERT(n < 32); /* this function currently doesn't handle n >= 32 */ if ((pgcell == cellnum) || FW_ISWR32(fwall[n][pgoffs], cellnum)) { /* good, we have write permission */ if (CPUVec.FirewallChange == 0) { fwall[n][pgoffs] = prot; } else { uint prot32 = prot; uint pgnum = n * ppn + pgoffs; uint cellmask = cpus_per_cell_mask<<(pgcell<<log2CPUS_PER_CELL(0)); uint oldprot = fwall[n][pgoffs]; uint grantmask = (prot32 & ~oldprot) & ~cellmask; uint denymask = (oldprot & ~prot32) & ~cellmask; /* the cellmask is there to avoid indicating a change for cpus that * are local to this page (and thus never change firewall * status irrespective of the bit values). */ fwall[n][pgoffs] = prot32; if (grantmask) { CPUVec.FirewallChange(pgnum * DEFAULT_PAGESZ, 1, grantmask); } if (denymask) { CPUVec.FirewallChange(pgnum * DEFAULT_PAGESZ, 0, denymask); } } return 0; } else { LogEntry("Illegal firewall write", cpu, "firewall for %x (cell %d) contents were %llx\n", n * ppn + pgoffs, pgcell, fwall[n][pgoffs]); return 1; }}uintCheckFirewallFast(int cpu, PA paddr){ /* return 1 if access allowed, 0 if violation * Note that we are in the memory system here: the remap should have already * occurred before this is called */ uint pgnum = PAGE_NUMBER(paddr); uint cellnum = cpu >> log2CPUS_PER_CELL(0); uint pgcell = pgnum >> log2ppcell; uint pgnode = pgnum >> log2ppn; uint pgoffs = pgnum & ppnodemask; return (pgcell == cellnum) || FW_ISWR32(fwall[pgnode][pgoffs], cellnum);}uintCheckFirewallSlow(int cpu, PA paddr){ uint pgnum = PAGE_NUMBER(paddr); uint cellnum = cpu >> log2CPUS_PER_CELL(0); uint pgcell = pgnum / ppcell; uint pgnode = pgnum / ppn; uint pgoffs = pgnum % ppn; return (pgcell == cellnum) || FW_ISWR(fwall[pgnode][pgoffs], cellnum);}voidsim_firewall_init(int restoreFromCkpt, int n, int pg_per_node){ char name[128]; int i; ASSERT(0 < n && n <= SIM_MAXCPUS); for (i = 0; i < n; i++) { sprintf(name, "FWALL_%d", i); fwall[i] = (uint64*)ZMALLOC(pg_per_node*sizeof(uint64), name); } fwn = n; ppn = pg_per_node; ppcell = ppn * CPUS_PER_CELL(0); Simcpt_Register("firewall", FirewallCheckpointCB, ALL_CPUS); if (restoreFromCkpt) { Simcpt_Restore("firewall");#ifdef FLASH_HACK FlashliteFirewallInit();#endif /* FLASH_HACK */ } else { firewall_enabled_flag = NUM_CELLS(0) > 1; } if ((NUM_CELLS(0) < 32) && ((pg_per_node & (pg_per_node-1)) == 0)) { CPUVec.CheckFirewall = CheckFirewallFast; log2ppcell = GetLog2(ppcell); log2ppn = GetLog2(pg_per_node); ppnodemask = pg_per_node-1; } else { CPUVec.CheckFirewall = CheckFirewallSlow; } if (!firewall_enabled_flag) { CPUVec.CheckFirewall = 0; } cpus_per_cell_mask = (1 << CPUS_PER_CELL(0)) - 1;}/* Checkpointing support */static intFirewallCheckpointCB(CptDescriptor *cptd){ int i; /* for compatibility with version 3 checkpoints */ if (cptVersion.ver == 3) { Simcpt_CptInt(cptd, "NumCells", NO_INDEX, NO_INDEX, &(NUM_CELLS(0))); } /* XXX old checkpoints used to set numCells to 0 for simport boots. * If we're restoring from a checkpoint and that's the case, then * we're done here. */ if (cptd->mode == CPT_RESTORE && NUM_CELLS(0) == 0) { NUM_CELLS(0) = 1; return 0; } ASSERT(NUM_CELLS(0) != 0); /* XXX the following is not compatible with the old checkpoint format. * No need to provide compatibility, since old simport checkpoints * don't use the firewall. */ Simcpt_OptionalUint(cptd, "FirewallEnabled",NO_INDEX,NO_INDEX,1); Simcpt_CptUint(cptd, "FirewallEnabled",NO_INDEX,NO_INDEX, &firewall_enabled_flag); Simcpt_CptHex(cptd, "PagesPerNode",NO_INDEX,NO_INDEX,(uint*)&ppn); for (i = 0; i < NUM_CPUS(0); i++) { Simcpt_CptBlock(cptd, "FWArray", i, NO_INDEX, fwall[i], ppn*sizeof(uint64)/sizeof(char), -1); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -