FILE *logfile;
int loglevel;
-
#ifdef MAPCACHE
pthread_mutex_t mapcache_mutex;
#endif
-
void cpu_exec_init(CPUState *env)
{
CPUState **penv;
return 0;
}
-static inline int paddr_is_ram(target_phys_addr_t addr)
-{
- /* Is this guest physical address RAM-backed? */
-#if defined(CONFIG_DM) && (defined(__i386__) || defined(__x86_64__))
- return ((addr < HVM_BELOW_4G_MMIO_START) ||
- (addr >= HVM_BELOW_4G_MMIO_START + HVM_BELOW_4G_MMIO_LENGTH));
-#else
- return (addr < ram_size);
-#endif
-}
-
#if defined(__i386__) || defined(__x86_64__)
#define phys_ram_addr(x) (qemu_map_cache(x))
#elif defined(__ia64__)
-#define phys_ram_addr(x) (phys_ram_base + (x))
+#define phys_ram_addr(x) ((addr < ram_size) ? (phys_ram_base + (x)) : NULL)
#endif
extern unsigned long *logdirty_bitmap;
io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
l = 1;
}
- } else if (paddr_is_ram(addr)) {
+ } else if ((ptr = phys_ram_addr(addr)) != NULL) {
/* Writing to RAM */
- ptr = phys_ram_addr(addr);
memcpy(ptr, buf, l);
if (logdirty_bitmap != NULL) {
/* Record that we have dirtied this frame */
unsigned long pfn = addr >> TARGET_PAGE_BITS;
if (pfn / 8 >= logdirty_bitmap_size) {
- fprintf(logfile, "dirtying pfn %x >= bitmap size %x\n",
- pfn, logdirty_bitmap_size * 8);
+ fprintf(logfile, "dirtying pfn %lx >= bitmap "
+ "size %lx\n", pfn, logdirty_bitmap_size * 8);
} else {
logdirty_bitmap[pfn / HOST_LONG_BITS]
|= 1UL << pfn % HOST_LONG_BITS;
stb_raw(buf, val);
l = 1;
}
- } else if (paddr_is_ram(addr)) {
+ } else if ((ptr = phys_ram_addr(addr)) != NULL) {
/* Reading from RAM */
- ptr = phys_ram_addr(addr);
memcpy(buf, ptr, l);
} else {
/* Neither RAM nor known MMIO space */
suspend_requested = 1;
}
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(MAPCACHE)
+
+#if defined(__i386__)
+#define MAX_MCACHE_SIZE 0x40000000 /* 1GB max for x86 */
+#define MCACHE_BUCKET_SHIFT 16
+#elif defined(__x86_64__)
+#define MAX_MCACHE_SIZE 0x1000000000 /* 64GB max for x86_64 */
+#define MCACHE_BUCKET_SHIFT 20
+#endif
+
+#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT)
+
+#define BITS_PER_LONG (sizeof(long)*8)
+#define BITS_TO_LONGS(bits) \
+ (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
+#define DECLARE_BITMAP(name,bits) \
+ unsigned long name[BITS_TO_LONGS(bits)]
+#define test_bit(bit,map) \
+ (!!((map)[(bit)/BITS_PER_LONG] & (1UL << ((bit)%BITS_PER_LONG))))
+
+struct map_cache {
+ unsigned long paddr_index;
+ uint8_t *vaddr_base;
+ DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE>>PAGE_SHIFT);
+};
+
static struct map_cache *mapcache_entry;
static unsigned long nr_buckets;
return 0;
}
+static void qemu_remap_bucket(struct map_cache *entry,
+ unsigned long address_index)
+{
+ uint8_t *vaddr_base;
+ unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT];
+ unsigned int i, j;
+
+ if (entry->vaddr_base != NULL) {
+ errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE);
+ if (errno) {
+ fprintf(logfile, "unmap fails %d\n", errno);
+ exit(-1);
+ }
+ }
+
+ for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++)
+ pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i;
+
+ vaddr_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE,
+ pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT);
+ if (vaddr_base == NULL) {
+ fprintf(logfile, "xc_map_foreign_batch error %d\n", errno);
+ exit(-1);
+ }
+
+ entry->vaddr_base = vaddr_base;
+ entry->paddr_index = address_index;
+
+ for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i += BITS_PER_LONG) {
+ unsigned long word = 0;
+ j = ((i + BITS_PER_LONG) > (MCACHE_BUCKET_SIZE >> PAGE_SHIFT)) ?
+ (MCACHE_BUCKET_SIZE >> PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG;
+ while (j > 0)
+ word = (word << 1) | !(pfns[i + --j] & 0xF0000000UL);
+ entry->valid_mapping[i / BITS_PER_LONG] = word;
+ }
+}
+
uint8_t *qemu_map_cache(target_phys_addr_t phys_addr)
{
struct map_cache *entry;
entry = &mapcache_entry[address_index % nr_buckets];
- if (entry->vaddr_base == NULL || entry->paddr_index != address_index) {
- /* We need to remap a bucket. */
- uint8_t *vaddr_base;
- unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT];
- unsigned int i;
-
- if (entry->vaddr_base != NULL) {
- errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE);
- if (errno) {
- fprintf(logfile, "unmap fails %d\n", errno);
- exit(-1);
- }
- }
+ if (entry->vaddr_base == NULL || entry->paddr_index != address_index ||
+ !test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping))
+ qemu_remap_bucket(entry, address_index);
- for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++)
- pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i;
-
- vaddr_base = xc_map_foreign_batch(
- xc_handle, domid, PROT_READ|PROT_WRITE,
- pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT);
- if (vaddr_base == NULL) {
- fprintf(logfile, "xc_map_foreign_batch error %d\n", errno);
- exit(-1);
- }
-
- entry->vaddr_base = vaddr_base;
- entry->paddr_index = address_index;;
- }
+ if (!test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping))
+ return NULL;
last_address_index = address_index;
last_address_vaddr = entry->vaddr_base;
mapcache_unlock();
}
-#endif
+
+#endif /* defined(MAPCACHE) */
int main(int argc, char **argv)
{