--- trunk/src/memory.c 2007/10/08 16:18:00 4 +++ trunk/src/memory.c 2007/10/08 16:18:38 12 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: memory.c,v 1.164 2005/04/09 21:10:54 debug Exp $ + * $Id: memory.c,v 1.175 2005/08/14 15:47:36 debug Exp $ * * Functions for handling the memory of an emulated machine. */ @@ -108,7 +108,7 @@ * zeroed_alloc(): * * Allocates a block of memory using mmap(), and if that fails, try - * malloc() + memset(). + * malloc() + memset(). The returned memory block contains only zeroes. */ void *zeroed_alloc(size_t s) { @@ -132,7 +132,7 @@ * This function creates a new memory object. An emulated machine needs one * of these. */ -struct memory *memory_new(uint64_t physical_max) +struct memory *memory_new(uint64_t physical_max, int arch) { struct memory *mem; int bits_per_pagetable = BITS_PER_PAGETABLE; @@ -157,6 +157,9 @@ } mem->physical_max = physical_max; + mem->dev_dyntrans_alignment = 4095; + if (arch == ARCH_ALPHA) + mem->dev_dyntrans_alignment = 8191; s = entries_per_pagetable * sizeof(void *); @@ -253,14 +256,13 @@ /* - * memory_device_bintrans_access(): + * memory_device_dyntrans_access(): * - * Get the lowest and highest bintrans access since last time. + * Get the lowest and highest dyntrans (or bintrans) access since last time. */ -void memory_device_bintrans_access(struct cpu *cpu, struct memory *mem, +void memory_device_dyntrans_access(struct cpu *cpu, struct memory *mem, void *extra, uint64_t *low, uint64_t *high) { -#ifdef BINTRANS int i, j; size_t s; int need_inval = 0; @@ -271,52 +273,53 @@ for (i=0; in_mmapped_devices; i++) { if (mem->dev_extra[i] == extra && - mem->dev_bintrans_data[i] != NULL) { - if (mem->dev_bintrans_write_low[i] != (uint64_t) -1) + mem->dev_dyntrans_data[i] != NULL) { + if (mem->dev_dyntrans_write_low[i] != (uint64_t) -1) need_inval = 1; if (low != NULL) - *low = mem->dev_bintrans_write_low[i]; - mem->dev_bintrans_write_low[i] = (uint64_t) -1; + *low = mem->dev_dyntrans_write_low[i]; + mem->dev_dyntrans_write_low[i] = (uint64_t) -1; if (high != NULL) - *high = mem->dev_bintrans_write_high[i]; - mem->dev_bintrans_write_high[i] = 0; + *high = mem->dev_dyntrans_write_high[i]; + mem->dev_dyntrans_write_high[i] = 0; if (!need_inval) return; - if (cpu->machine->arch != ARCH_MIPS) { - /* TODO! */ - - return; - } - /* Invalidate any pages of this device that might - be in the bintrans load/store cache, by marking + be in the dyntrans load/store cache, by marking the pages read-only. */ - - for (s=0; sdev_length[i]; s+=4096) { - mips_invalidate_translation_caches_paddr( - cpu, mem->dev_baseaddr[i] + s); + if (cpu->invalidate_translation_caches_paddr != NULL) { + for (s=0; sdev_length[i]; + s+=cpu->machine->arch_pagesize) + cpu->invalidate_translation_caches_paddr + (cpu, mem->dev_baseaddr[i] + s); } - /* ... and invalidate the "fast_vaddr_to_hostaddr" - cache entries that contain pointers to this - device: (NOTE: Device i, cache entry j) */ - for (j=0; jcd.mips.bintrans_data_hostpage[j] >= - mem->dev_bintrans_data[i] && - cpu->cd.mips.bintrans_data_hostpage[j] < - mem->dev_bintrans_data[i] + - mem->dev_length[i]) - cpu->cd.mips. - bintrans_data_hostpage[j] = NULL; + if (cpu->machine->arch == ARCH_MIPS) { + /* + * ... and invalidate the "fast_vaddr_to_ + * hostaddr" cache entries that contain + * pointers to this device: (NOTE: Device i, + * cache entry j) + */ + for (j=0; jcd. + mips.bintrans_data_hostpage[j] >= + mem->dev_dyntrans_data[i] && + cpu->cd.mips. + bintrans_data_hostpage[j] < + mem->dev_dyntrans_data[i] + + mem->dev_length[i]) + cpu->cd.mips. + bintrans_data_hostpage[j] + = NULL; + } } - return; } } -#endif } @@ -356,7 +359,7 @@ uint64_t baseaddr, uint64_t len, int (*f)(struct cpu *,struct memory *,uint64_t,unsigned char *, size_t,int,void *), - void *extra, int flags, unsigned char *bintrans_data) + void *extra, int flags, unsigned char *dyntrans_data) { int i; @@ -383,49 +386,54 @@ debug("device %2i at 0x%010llx: %s", mem->n_mmapped_devices, (long long)baseaddr, device_name); -#ifdef BINTRANS - if (flags & (MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK) - && (baseaddr & 0xfff) != 0) { - fatal("\nWARNING: Device bintrans access, but unaligned" + if (flags & (MEM_DYNTRANS_OK | MEM_DYNTRANS_WRITE_OK) + && (baseaddr & mem->dev_dyntrans_alignment) != 0) { + fatal("\nWARNING: Device dyntrans access, but unaligned" " baseaddr 0x%llx.\n", (long long)baseaddr); } - if (flags & (MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK)) { - debug(" (bintrans %s)", - (flags & MEM_BINTRANS_WRITE_OK)? "R/W" : "R"); + if (flags & (MEM_DYNTRANS_OK | MEM_DYNTRANS_WRITE_OK)) { + debug(" (dyntrans %s)", + (flags & MEM_DYNTRANS_WRITE_OK)? "R/W" : "R"); } -#endif debug("\n"); mem->dev_name[mem->n_mmapped_devices] = strdup(device_name); mem->dev_baseaddr[mem->n_mmapped_devices] = baseaddr; mem->dev_length[mem->n_mmapped_devices] = len; mem->dev_flags[mem->n_mmapped_devices] = flags; - mem->dev_bintrans_data[mem->n_mmapped_devices] = bintrans_data; + mem->dev_dyntrans_data[mem->n_mmapped_devices] = dyntrans_data; if (mem->dev_name[mem->n_mmapped_devices] == NULL) { fprintf(stderr, "out of memory\n"); exit(1); } - if ((size_t)bintrans_data & 1) { + if (flags & (MEM_DYNTRANS_OK | MEM_DYNTRANS_WRITE_OK) + && dyntrans_data == NULL) { + fatal("\nERROR: Device dyntrans access, but dyntrans_data" + " = NULL!\n"); + exit(1); + } + + if ((size_t)dyntrans_data & 7) { fprintf(stderr, "memory_device_register():" - " bintrans_data not aligned correctly\n"); + " dyntrans_data not aligned correctly (%p)\n", + dyntrans_data); exit(1); } -#ifdef BINTRANS - mem->dev_bintrans_write_low[mem->n_mmapped_devices] = (uint64_t)-1; - mem->dev_bintrans_write_high[mem->n_mmapped_devices] = 0; -#endif + mem->dev_dyntrans_write_low[mem->n_mmapped_devices] = (uint64_t)-1; + mem->dev_dyntrans_write_high[mem->n_mmapped_devices] = 0; mem->dev_f[mem->n_mmapped_devices] = f; mem->dev_extra[mem->n_mmapped_devices] = extra; mem->n_mmapped_devices++; if (baseaddr < mem->mmap_dev_minaddr) - mem->mmap_dev_minaddr = baseaddr & ~0xfff; + mem->mmap_dev_minaddr = baseaddr & ~mem->dev_dyntrans_alignment; if (baseaddr + len > mem->mmap_dev_maxaddr) - mem->mmap_dev_maxaddr = (((baseaddr + len) - 1) | 0xfff) + 1; + mem->mmap_dev_maxaddr = (((baseaddr + len) - 1) | + mem->dev_dyntrans_alignment) + 1; } @@ -464,14 +472,12 @@ (MAX_DEVICES - i - 1)); memmove(&mem->dev_f_state[i], &mem->dev_f_state[i+1], sizeof(void *) * (MAX_DEVICES - i - 1)); - memmove(&mem->dev_bintrans_data[i], &mem->dev_bintrans_data[i+1], + memmove(&mem->dev_dyntrans_data[i], &mem->dev_dyntrans_data[i+1], sizeof(void *) * (MAX_DEVICES - i - 1)); -#ifdef BINTRANS - memmove(&mem->dev_bintrans_write_low[i], &mem->dev_bintrans_write_low + memmove(&mem->dev_dyntrans_write_low[i], &mem->dev_dyntrans_write_low [i+1], sizeof(void *) * (MAX_DEVICES - i - 1)); - memmove(&mem->dev_bintrans_write_high[i], &mem->dev_bintrans_write_high + memmove(&mem->dev_dyntrans_write_high[i], &mem->dev_dyntrans_write_high [i+1], sizeof(void *) * (MAX_DEVICES - i - 1)); -#endif } @@ -501,7 +507,8 @@ table = mem->pagetable; entry = (paddr >> shrcount) & mask; - /* printf(" entry = %x\n", entry); */ + /* printf("memory_paddr_to_hostaddr(): p=%16llx w=%i => entry=0x%x\n", + (long long)paddr, writeflag, entry); */ if (table[entry] == NULL) { size_t alloclen;