⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 userflush.c

📁 一个用在mips体系结构中的操作系统
💻 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.  * *//* **************************************************** * File to maintain cache consistency after DCG * * Highly platform-specific. Only sgi and alpha versions * implemented so far. * ****************************************************/#include <stdio.h>#ifdef sgi#include <sys/cachectl.h>#include <bstring.h>#endif#ifdef __alpha#include <alpha/inst.h>#include <machine/pal.h>#endif#include <errno.h>#include <strings.h>#include "sim_error.h"#include "userflush.h"extern int errno;/* ************************************************************ * sgi version * ************************************************************/#ifdef sgi#define LOG2_CACHE_SIZE 15#define CACHE_LINE_SIZE 16#define JMP_RA_INST         0x03e00008#define ADDIU_LINESIZE_INT (0x24840000|((-CACHE_LINE_SIZE)&0xffff))#define BEQZ_A0_XXX_INST    0x10800000#define CACHE_SIZE    (1<<LOG2_CACHE_SIZE)#define CACHE_INDEX(_va) (_va & ((CACHE_SIZE-1)&~(CACHE_LINE_SIZE-1)))static char flushbuffermem[CACHE_SIZE*2+8];static char flushbuffermem2[CACHE_SIZE*2+8];unsigned int flushbuffer;unsigned int flushbuffer2;static int userflush_init = 0;int slowcacheflush(void *addr, int len, int cache){   return cacheflush(addr,len,cache);}int flushrange(unsigned int start, int nbytes, int cache);/* * This is a user level version of the cacheflush routine for mshade. Note * that it only works on the R4000 & R4400 and it only flushes the  * primary caches.  */void usercacheinit(void) {   int i;   flushbuffer = (unsigned int)       ((((unsigned int)flushbuffermem) + CACHE_SIZE) & ~(CACHE_SIZE-1));   flushbuffer2 = (unsigned int)       ((((unsigned int)flushbuffermem2) + CACHE_SIZE) & ~(CACHE_SIZE-1));   bzero((char *) flushbuffer, CACHE_SIZE+8); /* Fill with NOPs */   bzero((char *) flushbuffer2, CACHE_SIZE+8); /* Fill with NOPs */   for (i = 0; i < CACHE_SIZE; i += CACHE_LINE_SIZE) {      int o = i/sizeof(unsigned int);      ((int *)flushbuffer)[o] = ADDIU_LINESIZE_INT; /* add a0,a0,-LSIZE */      ((int *)flushbuffer)[o+1] =          BEQZ_A0_XXX_INST|((CACHE_SIZE-(i+8))/sizeof(unsigned int));      /* beq a0,zero, ret */   }   for (i = 0; i < CACHE_SIZE; i += CACHE_LINE_SIZE) {      int o = i/sizeof(unsigned int);      ((int *)flushbuffer2)[o] = ADDIU_LINESIZE_INT; /* add a0,a0,-LSIZE */      ((int *)flushbuffer2)[o+1] =          BEQZ_A0_XXX_INST|((CACHE_SIZE-(i+8))/sizeof(unsigned int));      /* beq a0,zero, ret */   }   ((int *)flushbuffer)[CACHE_SIZE/sizeof(unsigned int)] = JMP_RA_INST;   ((int *)flushbuffer2)[CACHE_SIZE/sizeof(unsigned int)] = JMP_RA_INST;   if (slowcacheflush((void *)flushbuffer, CACHE_SIZE+8, BCACHE) < 0) {      perror("flushing cache in userflush init");   }   if (cacheflush((void *)flushbuffer2, CACHE_SIZE+8, BCACHE) < 0) {      perror("flushing cache in userflush init");   }}  int usercacheflush(void *addr, int nbytes, int cache){    unsigned int start_addr, end_addr;    unsigned int start_offset;    int i;      if (!userflush_init) {       usercacheinit();       userflush_init = 1;    }    /*     * Round address to cache line boundries. Round down at start and     * up at end.     */    start_addr = (unsigned int)addr & ~(CACHE_LINE_SIZE-1);    end_addr = ((unsigned int)addr+nbytes+CACHE_LINE_SIZE-1) &                              ~(CACHE_LINE_SIZE-1);    /*     * We never need to flush more than the entire cache. Compute     * the start and range of bytes to read into the primary cache     * to flush the user buffer from it.  Note this assumes direct     * mapped i & d caches.     */    nbytes = end_addr - start_addr;    if (nbytes >= CACHE_SIZE) {       flushrange(0, CACHE_SIZE, cache);       return 0;    }    start_offset =  start_addr%CACHE_SIZE;    /*     * Detect the case of wrapping in the cache. Break this into     * two different range flushes.     */    if (start_offset + nbytes > CACHE_SIZE) {       (void) flushrange(start_offset, CACHE_SIZE-start_offset, cache);       flushrange(0, nbytes-(CACHE_SIZE-start_offset), cache);    } else {        flushrange(start_offset, nbytes, cache);    }    return 0;}struct {   int start;   int start2;   int nbytes;} bufLog[1024];int bufCount;void SyncInstr(void);intflushrange(unsigned int start, int nbytes, int cache){   int i,x=0;   int pid;   int start2 = start+flushbuffer2;   start += flushbuffer;   bufLog[bufCount].start = start;   bufLog[bufCount].start2 = start2;   bufLog[bufCount].nbytes = nbytes;      bufCount = (bufCount+1)%1024;;   if (cache==DCACHE || cache==BCACHE) {      for (i = 0; i < nbytes; i += CACHE_LINE_SIZE) {         x += ((volatile int *)(start + i))[0];         x += ((volatile int *)(start2 + i))[0];         ((volatile int *)(start + i))[0] =  ((volatile int *)(start + i))[0];         ((volatile int *)(start2 + i))[0] =  ((volatile int *)(start2 + i))[0];      }   }      SyncInstr();       if ((cache==ICACHE) || (cache==BCACHE)) {      ((void(*)(int))(start))(nbytes);      ((void(*)(int))(start2))(nbytes);   }   return x;}/* This version only flushes one line of the I-cache and the D-cache. * On the MIPS processors, inclusion of the I-cache is maintained * but coherency is not maintained. Both I and D caches MUST be flushed * if code is emitted at runtime. */int FlushOneLine(TCA tca) {  uint ca    = CACHE_INDEX((uint)tca);  uint addr1 = flushbuffer  + ca;  uint addr2 = flushbuffer2 + ca;  int x=0;  /* flush from both the I and D caches */  x +=((volatile int *)addr1)[0];  x +=((volatile int *)addr2)[0];  ((volatile int *)(addr1))[0] =  ((volatile int *)(addr1))[0];  ((volatile int *)(addr2))[0] =  ((volatile int *)(addr2))[0];    ((void(*)(int))addr1)(CACHE_LINE_SIZE);  ((void(*)(int))addr2)(CACHE_LINE_SIZE);  return x;}#endif /* sgi *//* ************************************************************** * alpha * **************************************************************/#ifdef __alpha#define LOG2_CACHE_SIZE 13  /* 8kb */#define CACHE_SIZE (1<<LOG2_CACHE_SIZE)#define CACHE_LINE_SIZE 16  /* bytes */#define HOST_PAGE_SIZE (1<<13)#define NEXT_HOST_PAGE(_x) ( ((size_t)(_x)+HOST_PAGE_SIZE-1) & ~(HOST_PAGE_SIZE-1))#define CCj(_opcode, _jsr, _ra, _rb, _disp) (uint32)(\                                       U(_opcode)<<26 | U(_ra)<<21| \                                       U(_rb)<<16 | U(_jsr)<<14 |   \                                       ((U(_disp)>>2) & 0x3FFF) ) #define REG_ZERO 31#define REG_RA   26static Inst buf_space[(CACHE_SIZE+HOST_PAGE_SIZE)/sizeof(Inst)];static union alpha_instruction *flushbuf;void usercacheinit(void){   int i;   union alpha_instruction inst;   inst.common.opcode = op_jsr;   inst.j_format.function = jsr_jsr;   inst.j_format.ra = REG_ZERO;   inst.j_format.rb = REG_RA;   inst.j_format.hint = 0;   flushbuf = (union alpha_instruction*)NEXT_HOST_PAGE(buf_space);   for (i=0;i<CACHE_SIZE/sizeof(Inst);i++) {      flushbuf[i] = inst;   }   usercacheflush(flushbuf,CACHE_SIZE,0);}/* ************************************************* * FlushOneLine. static function. Make sure to add * a "mb" before it.  * *************************************************/#define CACHE_SIZE_MASK ((CACHE_SIZE-1) & ~0x7)inline int FlushOneLine(TCA  tca) {     uint64 addr = (uint64)flushbuf+ (CACHE_SIZE_MASK&(uint64)tca);   volatile uint64 x = *(volatile uint64 *)addr;   *(volatile uint64*) addr = x;   ((void(*)()) addr)();   return 0;}int usercacheflush(void *addr, int len, int cache){   int i;   /* asm ("call_pal 0x86");*/ /* imb */#if 0   asm volatile ("mb"::);   for (i=0;i<=len;i+=CACHE_LINE_SIZE) {      FlushOneLine((TCA)((char*)addr+i));   } #endif    asm ("call_pal 0x86"); /* imb */    for(i=0;i<12;i++) {       ;    }   return 0;}int slowcacheflush(void *addr, int len, int cache){   /*    * imb done in usercacheflush already!    * asm ("call_pal 0x86");     */   if ( len >CACHE_SIZE) {      return usercacheflush(addr,CACHE_SIZE,cache);   } else {       return usercacheflush(addr,len,cache);   }}#endif /* __alpha */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -