qemu/include/exec/cpu_ldst.h
<<
>>
Prefs
   1/*
   2 *  Software MMU support
   3 *
   4 * This library is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU Lesser General Public
   6 * License as published by the Free Software Foundation; either
   7 * version 2 of the License, or (at your option) any later version.
   8 *
   9 * This library is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12 * Lesser General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU Lesser General Public
  15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  16 *
  17 */
  18
  19/*
  20 * Generate inline load/store functions for all MMU modes (typically
  21 * at least _user and _kernel) as well as _data versions, for all data
  22 * sizes.
  23 *
  24 * Used by target op helpers.
  25 *
  26 * The syntax for the accessors is:
  27 *
  28 * load: cpu_ld{sign}{size}_{mmusuffix}(env, ptr)
  29 *
  30 * store: cpu_st{sign}{size}_{mmusuffix}(env, ptr, val)
  31 *
  32 * sign is:
  33 * (empty): for 32 and 64 bit sizes
  34 *   u    : unsigned
  35 *   s    : signed
  36 *
  37 * size is:
  38 *   b: 8 bits
  39 *   w: 16 bits
  40 *   l: 32 bits
  41 *   q: 64 bits
  42 *
  43 * mmusuffix is one of the generic suffixes "data" or "code", or
  44 * (for softmmu configs)  a target-specific MMU mode suffix as defined
  45 * in target cpu.h.
  46 */
  47#ifndef CPU_LDST_H
  48#define CPU_LDST_H
  49
  50#if defined(CONFIG_USER_ONLY)
  51/* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
  52#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + guest_base))
  53
  54#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
  55#define h2g_valid(x) 1
  56#else
  57#define h2g_valid(x) ({ \
  58    unsigned long __guest = (unsigned long)(x) - guest_base; \
  59    (__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
  60    (!reserved_va || (__guest < reserved_va)); \
  61})
  62#endif
  63
  64#define h2g_nocheck(x) ({ \
  65    unsigned long __ret = (unsigned long)(x) - guest_base; \
  66    (abi_ulong)__ret; \
  67})
  68
  69#define h2g(x) ({ \
  70    /* Check if given address fits target address space */ \
  71    assert(h2g_valid(x)); \
  72    h2g_nocheck(x); \
  73})
  74
  75#endif
  76
  77#if defined(CONFIG_USER_ONLY)
  78
  79extern __thread uintptr_t helper_retaddr;
  80
  81/* In user-only mode we provide only the _code and _data accessors. */
  82
  83#define MEMSUFFIX _data
  84#define DATA_SIZE 1
  85#include "exec/cpu_ldst_useronly_template.h"
  86
  87#define DATA_SIZE 2
  88#include "exec/cpu_ldst_useronly_template.h"
  89
  90#define DATA_SIZE 4
  91#include "exec/cpu_ldst_useronly_template.h"
  92
  93#define DATA_SIZE 8
  94#include "exec/cpu_ldst_useronly_template.h"
  95#undef MEMSUFFIX
  96
  97#define MEMSUFFIX _code
  98#define CODE_ACCESS
  99#define DATA_SIZE 1
 100#include "exec/cpu_ldst_useronly_template.h"
 101
 102#define DATA_SIZE 2
 103#include "exec/cpu_ldst_useronly_template.h"
 104
 105#define DATA_SIZE 4
 106#include "exec/cpu_ldst_useronly_template.h"
 107
 108#define DATA_SIZE 8
 109#include "exec/cpu_ldst_useronly_template.h"
 110#undef MEMSUFFIX
 111#undef CODE_ACCESS
 112
 113#else
 114
 115/* The memory helpers for tcg-generated code need tcg_target_long etc.  */
 116#include "tcg.h"
 117
 118#ifdef MMU_MODE0_SUFFIX
 119#define CPU_MMU_INDEX 0
 120#define MEMSUFFIX MMU_MODE0_SUFFIX
 121#define DATA_SIZE 1
 122#include "exec/cpu_ldst_template.h"
 123
 124#define DATA_SIZE 2
 125#include "exec/cpu_ldst_template.h"
 126
 127#define DATA_SIZE 4
 128#include "exec/cpu_ldst_template.h"
 129
 130#define DATA_SIZE 8
 131#include "exec/cpu_ldst_template.h"
 132#undef CPU_MMU_INDEX
 133#undef MEMSUFFIX
 134#endif
 135
 136#if (NB_MMU_MODES >= 2) && defined(MMU_MODE1_SUFFIX)
 137#define CPU_MMU_INDEX 1
 138#define MEMSUFFIX MMU_MODE1_SUFFIX
 139#define DATA_SIZE 1
 140#include "exec/cpu_ldst_template.h"
 141
 142#define DATA_SIZE 2
 143#include "exec/cpu_ldst_template.h"
 144
 145#define DATA_SIZE 4
 146#include "exec/cpu_ldst_template.h"
 147
 148#define DATA_SIZE 8
 149#include "exec/cpu_ldst_template.h"
 150#undef CPU_MMU_INDEX
 151#undef MEMSUFFIX
 152#endif
 153
 154#if (NB_MMU_MODES >= 3) && defined(MMU_MODE2_SUFFIX)
 155
 156#define CPU_MMU_INDEX 2
 157#define MEMSUFFIX MMU_MODE2_SUFFIX
 158#define DATA_SIZE 1
 159#include "exec/cpu_ldst_template.h"
 160
 161#define DATA_SIZE 2
 162#include "exec/cpu_ldst_template.h"
 163
 164#define DATA_SIZE 4
 165#include "exec/cpu_ldst_template.h"
 166
 167#define DATA_SIZE 8
 168#include "exec/cpu_ldst_template.h"
 169#undef CPU_MMU_INDEX
 170#undef MEMSUFFIX
 171#endif /* (NB_MMU_MODES >= 3) */
 172
 173#if (NB_MMU_MODES >= 4) && defined(MMU_MODE3_SUFFIX)
 174
 175#define CPU_MMU_INDEX 3
 176#define MEMSUFFIX MMU_MODE3_SUFFIX
 177#define DATA_SIZE 1
 178#include "exec/cpu_ldst_template.h"
 179
 180#define DATA_SIZE 2
 181#include "exec/cpu_ldst_template.h"
 182
 183#define DATA_SIZE 4
 184#include "exec/cpu_ldst_template.h"
 185
 186#define DATA_SIZE 8
 187#include "exec/cpu_ldst_template.h"
 188#undef CPU_MMU_INDEX
 189#undef MEMSUFFIX
 190#endif /* (NB_MMU_MODES >= 4) */
 191
 192#if (NB_MMU_MODES >= 5) && defined(MMU_MODE4_SUFFIX)
 193
 194#define CPU_MMU_INDEX 4
 195#define MEMSUFFIX MMU_MODE4_SUFFIX
 196#define DATA_SIZE 1
 197#include "exec/cpu_ldst_template.h"
 198
 199#define DATA_SIZE 2
 200#include "exec/cpu_ldst_template.h"
 201
 202#define DATA_SIZE 4
 203#include "exec/cpu_ldst_template.h"
 204
 205#define DATA_SIZE 8
 206#include "exec/cpu_ldst_template.h"
 207#undef CPU_MMU_INDEX
 208#undef MEMSUFFIX
 209#endif /* (NB_MMU_MODES >= 5) */
 210
 211#if (NB_MMU_MODES >= 6) && defined(MMU_MODE5_SUFFIX)
 212
 213#define CPU_MMU_INDEX 5
 214#define MEMSUFFIX MMU_MODE5_SUFFIX
 215#define DATA_SIZE 1
 216#include "exec/cpu_ldst_template.h"
 217
 218#define DATA_SIZE 2
 219#include "exec/cpu_ldst_template.h"
 220
 221#define DATA_SIZE 4
 222#include "exec/cpu_ldst_template.h"
 223
 224#define DATA_SIZE 8
 225#include "exec/cpu_ldst_template.h"
 226#undef CPU_MMU_INDEX
 227#undef MEMSUFFIX
 228#endif /* (NB_MMU_MODES >= 6) */
 229
 230#if (NB_MMU_MODES >= 7) && defined(MMU_MODE6_SUFFIX)
 231
 232#define CPU_MMU_INDEX 6
 233#define MEMSUFFIX MMU_MODE6_SUFFIX
 234#define DATA_SIZE 1
 235#include "exec/cpu_ldst_template.h"
 236
 237#define DATA_SIZE 2
 238#include "exec/cpu_ldst_template.h"
 239
 240#define DATA_SIZE 4
 241#include "exec/cpu_ldst_template.h"
 242
 243#define DATA_SIZE 8
 244#include "exec/cpu_ldst_template.h"
 245#undef CPU_MMU_INDEX
 246#undef MEMSUFFIX
 247#endif /* (NB_MMU_MODES >= 7) */
 248
 249#if (NB_MMU_MODES >= 8) && defined(MMU_MODE7_SUFFIX)
 250
 251#define CPU_MMU_INDEX 7
 252#define MEMSUFFIX MMU_MODE7_SUFFIX
 253#define DATA_SIZE 1
 254#include "exec/cpu_ldst_template.h"
 255
 256#define DATA_SIZE 2
 257#include "exec/cpu_ldst_template.h"
 258
 259#define DATA_SIZE 4
 260#include "exec/cpu_ldst_template.h"
 261
 262#define DATA_SIZE 8
 263#include "exec/cpu_ldst_template.h"
 264#undef CPU_MMU_INDEX
 265#undef MEMSUFFIX
 266#endif /* (NB_MMU_MODES >= 8) */
 267
 268#if (NB_MMU_MODES >= 9) && defined(MMU_MODE8_SUFFIX)
 269
 270#define CPU_MMU_INDEX 8
 271#define MEMSUFFIX MMU_MODE8_SUFFIX
 272#define DATA_SIZE 1
 273#include "exec/cpu_ldst_template.h"
 274
 275#define DATA_SIZE 2
 276#include "exec/cpu_ldst_template.h"
 277
 278#define DATA_SIZE 4
 279#include "exec/cpu_ldst_template.h"
 280
 281#define DATA_SIZE 8
 282#include "exec/cpu_ldst_template.h"
 283#undef CPU_MMU_INDEX
 284#undef MEMSUFFIX
 285#endif /* (NB_MMU_MODES >= 9) */
 286
 287#if (NB_MMU_MODES >= 10) && defined(MMU_MODE9_SUFFIX)
 288
 289#define CPU_MMU_INDEX 9
 290#define MEMSUFFIX MMU_MODE9_SUFFIX
 291#define DATA_SIZE 1
 292#include "exec/cpu_ldst_template.h"
 293
 294#define DATA_SIZE 2
 295#include "exec/cpu_ldst_template.h"
 296
 297#define DATA_SIZE 4
 298#include "exec/cpu_ldst_template.h"
 299
 300#define DATA_SIZE 8
 301#include "exec/cpu_ldst_template.h"
 302#undef CPU_MMU_INDEX
 303#undef MEMSUFFIX
 304#endif /* (NB_MMU_MODES >= 10) */
 305
 306#if (NB_MMU_MODES >= 11) && defined(MMU_MODE10_SUFFIX)
 307
 308#define CPU_MMU_INDEX 10
 309#define MEMSUFFIX MMU_MODE10_SUFFIX
 310#define DATA_SIZE 1
 311#include "exec/cpu_ldst_template.h"
 312
 313#define DATA_SIZE 2
 314#include "exec/cpu_ldst_template.h"
 315
 316#define DATA_SIZE 4
 317#include "exec/cpu_ldst_template.h"
 318
 319#define DATA_SIZE 8
 320#include "exec/cpu_ldst_template.h"
 321#undef CPU_MMU_INDEX
 322#undef MEMSUFFIX
 323#endif /* (NB_MMU_MODES >= 11) */
 324
 325#if (NB_MMU_MODES >= 12) && defined(MMU_MODE11_SUFFIX)
 326
 327#define CPU_MMU_INDEX 11
 328#define MEMSUFFIX MMU_MODE11_SUFFIX
 329#define DATA_SIZE 1
 330#include "exec/cpu_ldst_template.h"
 331
 332#define DATA_SIZE 2
 333#include "exec/cpu_ldst_template.h"
 334
 335#define DATA_SIZE 4
 336#include "exec/cpu_ldst_template.h"
 337
 338#define DATA_SIZE 8
 339#include "exec/cpu_ldst_template.h"
 340#undef CPU_MMU_INDEX
 341#undef MEMSUFFIX
 342#endif /* (NB_MMU_MODES >= 12) */
 343
 344#if (NB_MMU_MODES > 12)
 345#error "NB_MMU_MODES > 12 is not supported for now"
 346#endif /* (NB_MMU_MODES > 12) */
 347
 348/* these access are slower, they must be as rare as possible */
 349#define CPU_MMU_INDEX (cpu_mmu_index(env, false))
 350#define MEMSUFFIX _data
 351#define DATA_SIZE 1
 352#include "exec/cpu_ldst_template.h"
 353
 354#define DATA_SIZE 2
 355#include "exec/cpu_ldst_template.h"
 356
 357#define DATA_SIZE 4
 358#include "exec/cpu_ldst_template.h"
 359
 360#define DATA_SIZE 8
 361#include "exec/cpu_ldst_template.h"
 362#undef CPU_MMU_INDEX
 363#undef MEMSUFFIX
 364
 365#define CPU_MMU_INDEX (cpu_mmu_index(env, true))
 366#define MEMSUFFIX _code
 367#define SOFTMMU_CODE_ACCESS
 368
 369#define DATA_SIZE 1
 370#include "exec/cpu_ldst_template.h"
 371
 372#define DATA_SIZE 2
 373#include "exec/cpu_ldst_template.h"
 374
 375#define DATA_SIZE 4
 376#include "exec/cpu_ldst_template.h"
 377
 378#define DATA_SIZE 8
 379#include "exec/cpu_ldst_template.h"
 380
 381#undef CPU_MMU_INDEX
 382#undef MEMSUFFIX
 383#undef SOFTMMU_CODE_ACCESS
 384
 385#endif /* defined(CONFIG_USER_ONLY) */
 386
 387/**
 388 * tlb_vaddr_to_host:
 389 * @env: CPUArchState
 390 * @addr: guest virtual address to look up
 391 * @access_type: 0 for read, 1 for write, 2 for execute
 392 * @mmu_idx: MMU index to use for lookup
 393 *
 394 * Look up the specified guest virtual index in the TCG softmmu TLB.
 395 * If the TLB contains a host virtual address suitable for direct RAM
 396 * access, then return it. Otherwise (TLB miss, TLB entry is for an
 397 * I/O access, etc) return NULL.
 398 *
 399 * This is the equivalent of the initial fast-path code used by
 400 * TCG backends for guest load and store accesses.
 401 */
 402static inline void *tlb_vaddr_to_host(CPUArchState *env, target_ulong addr,
 403                                      int access_type, int mmu_idx)
 404{
 405#if defined(CONFIG_USER_ONLY)
 406    return g2h(addr);
 407#else
 408    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
 409    CPUTLBEntry *tlbentry = &env->tlb_table[mmu_idx][index];
 410    target_ulong tlb_addr;
 411    uintptr_t haddr;
 412
 413    switch (access_type) {
 414    case 0:
 415        tlb_addr = tlbentry->addr_read;
 416        break;
 417    case 1:
 418        tlb_addr = tlbentry->addr_write;
 419        break;
 420    case 2:
 421        tlb_addr = tlbentry->addr_code;
 422        break;
 423    default:
 424        g_assert_not_reached();
 425    }
 426
 427    if ((addr & TARGET_PAGE_MASK)
 428        != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
 429        /* TLB entry is for a different page */
 430        return NULL;
 431    }
 432
 433    if (tlb_addr & ~TARGET_PAGE_MASK) {
 434        /* IO access */
 435        return NULL;
 436    }
 437
 438    haddr = addr + env->tlb_table[mmu_idx][index].addend;
 439    return (void *)haddr;
 440#endif /* defined(CONFIG_USER_ONLY) */
 441}
 442
 443#endif /* CPU_LDST_H */
 444