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/* sparc32plus has 64bit long but 32bit space address
  52 * this can make bad result with g2h() and h2g()
  53 */
  54#if TARGET_VIRT_ADDR_SPACE_BITS <= 32
  55typedef uint32_t abi_ptr;
  56#define TARGET_ABI_FMT_ptr "%x"
  57#else
  58typedef uint64_t abi_ptr;
  59#define TARGET_ABI_FMT_ptr "%"PRIx64
  60#endif
  61
  62/* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
  63#define g2h(x) ((void *)((unsigned long)(abi_ptr)(x) + guest_base))
  64
  65#define guest_addr_valid(x) ((x) <= GUEST_ADDR_MAX)
  66#define h2g_valid(x) guest_addr_valid((unsigned long)(x) - guest_base)
  67
  68static inline int guest_range_valid(unsigned long start, unsigned long len)
  69{
  70    return len - 1 <= GUEST_ADDR_MAX && start <= GUEST_ADDR_MAX - len + 1;
  71}
  72
  73#define h2g_nocheck(x) ({ \
  74    unsigned long __ret = (unsigned long)(x) - guest_base; \
  75    (abi_ptr)__ret; \
  76})
  77
  78#define h2g(x) ({ \
  79    /* Check if given address fits target address space */ \
  80    assert(h2g_valid(x)); \
  81    h2g_nocheck(x); \
  82})
  83#else
  84typedef target_ulong abi_ptr;
  85#define TARGET_ABI_FMT_ptr TARGET_ABI_FMT_lx
  86#endif
  87
  88#if defined(CONFIG_USER_ONLY)
  89
  90extern __thread uintptr_t helper_retaddr;
  91
  92/* In user-only mode we provide only the _code and _data accessors. */
  93
  94#define MEMSUFFIX _data
  95#define DATA_SIZE 1
  96#include "exec/cpu_ldst_useronly_template.h"
  97
  98#define DATA_SIZE 2
  99#include "exec/cpu_ldst_useronly_template.h"
 100
 101#define DATA_SIZE 4
 102#include "exec/cpu_ldst_useronly_template.h"
 103
 104#define DATA_SIZE 8
 105#include "exec/cpu_ldst_useronly_template.h"
 106#undef MEMSUFFIX
 107
 108#define MEMSUFFIX _code
 109#define CODE_ACCESS
 110#define DATA_SIZE 1
 111#include "exec/cpu_ldst_useronly_template.h"
 112
 113#define DATA_SIZE 2
 114#include "exec/cpu_ldst_useronly_template.h"
 115
 116#define DATA_SIZE 4
 117#include "exec/cpu_ldst_useronly_template.h"
 118
 119#define DATA_SIZE 8
 120#include "exec/cpu_ldst_useronly_template.h"
 121#undef MEMSUFFIX
 122#undef CODE_ACCESS
 123
 124#else
 125
 126/* The memory helpers for tcg-generated code need tcg_target_long etc.  */
 127#include "tcg.h"
 128
 129static inline target_ulong tlb_addr_write(const CPUTLBEntry *entry)
 130{
 131#if TCG_OVERSIZED_GUEST
 132    return entry->addr_write;
 133#else
 134    return atomic_read(&entry->addr_write);
 135#endif
 136}
 137
 138/* Find the TLB index corresponding to the mmu_idx + address pair.  */
 139static inline uintptr_t tlb_index(CPUArchState *env, uintptr_t mmu_idx,
 140                                  target_ulong addr)
 141{
 142    return (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
 143}
 144
 145/* Find the TLB entry corresponding to the mmu_idx + address pair.  */
 146static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
 147                                     target_ulong addr)
 148{
 149    return &env->tlb_table[mmu_idx][tlb_index(env, mmu_idx, addr)];
 150}
 151
 152#ifdef MMU_MODE0_SUFFIX
 153#define CPU_MMU_INDEX 0
 154#define MEMSUFFIX MMU_MODE0_SUFFIX
 155#define DATA_SIZE 1
 156#include "exec/cpu_ldst_template.h"
 157
 158#define DATA_SIZE 2
 159#include "exec/cpu_ldst_template.h"
 160
 161#define DATA_SIZE 4
 162#include "exec/cpu_ldst_template.h"
 163
 164#define DATA_SIZE 8
 165#include "exec/cpu_ldst_template.h"
 166#undef CPU_MMU_INDEX
 167#undef MEMSUFFIX
 168#endif
 169
 170#if (NB_MMU_MODES >= 2) && defined(MMU_MODE1_SUFFIX)
 171#define CPU_MMU_INDEX 1
 172#define MEMSUFFIX MMU_MODE1_SUFFIX
 173#define DATA_SIZE 1
 174#include "exec/cpu_ldst_template.h"
 175
 176#define DATA_SIZE 2
 177#include "exec/cpu_ldst_template.h"
 178
 179#define DATA_SIZE 4
 180#include "exec/cpu_ldst_template.h"
 181
 182#define DATA_SIZE 8
 183#include "exec/cpu_ldst_template.h"
 184#undef CPU_MMU_INDEX
 185#undef MEMSUFFIX
 186#endif
 187
 188#if (NB_MMU_MODES >= 3) && defined(MMU_MODE2_SUFFIX)
 189
 190#define CPU_MMU_INDEX 2
 191#define MEMSUFFIX MMU_MODE2_SUFFIX
 192#define DATA_SIZE 1
 193#include "exec/cpu_ldst_template.h"
 194
 195#define DATA_SIZE 2
 196#include "exec/cpu_ldst_template.h"
 197
 198#define DATA_SIZE 4
 199#include "exec/cpu_ldst_template.h"
 200
 201#define DATA_SIZE 8
 202#include "exec/cpu_ldst_template.h"
 203#undef CPU_MMU_INDEX
 204#undef MEMSUFFIX
 205#endif /* (NB_MMU_MODES >= 3) */
 206
 207#if (NB_MMU_MODES >= 4) && defined(MMU_MODE3_SUFFIX)
 208
 209#define CPU_MMU_INDEX 3
 210#define MEMSUFFIX MMU_MODE3_SUFFIX
 211#define DATA_SIZE 1
 212#include "exec/cpu_ldst_template.h"
 213
 214#define DATA_SIZE 2
 215#include "exec/cpu_ldst_template.h"
 216
 217#define DATA_SIZE 4
 218#include "exec/cpu_ldst_template.h"
 219
 220#define DATA_SIZE 8
 221#include "exec/cpu_ldst_template.h"
 222#undef CPU_MMU_INDEX
 223#undef MEMSUFFIX
 224#endif /* (NB_MMU_MODES >= 4) */
 225
 226#if (NB_MMU_MODES >= 5) && defined(MMU_MODE4_SUFFIX)
 227
 228#define CPU_MMU_INDEX 4
 229#define MEMSUFFIX MMU_MODE4_SUFFIX
 230#define DATA_SIZE 1
 231#include "exec/cpu_ldst_template.h"
 232
 233#define DATA_SIZE 2
 234#include "exec/cpu_ldst_template.h"
 235
 236#define DATA_SIZE 4
 237#include "exec/cpu_ldst_template.h"
 238
 239#define DATA_SIZE 8
 240#include "exec/cpu_ldst_template.h"
 241#undef CPU_MMU_INDEX
 242#undef MEMSUFFIX
 243#endif /* (NB_MMU_MODES >= 5) */
 244
 245#if (NB_MMU_MODES >= 6) && defined(MMU_MODE5_SUFFIX)
 246
 247#define CPU_MMU_INDEX 5
 248#define MEMSUFFIX MMU_MODE5_SUFFIX
 249#define DATA_SIZE 1
 250#include "exec/cpu_ldst_template.h"
 251
 252#define DATA_SIZE 2
 253#include "exec/cpu_ldst_template.h"
 254
 255#define DATA_SIZE 4
 256#include "exec/cpu_ldst_template.h"
 257
 258#define DATA_SIZE 8
 259#include "exec/cpu_ldst_template.h"
 260#undef CPU_MMU_INDEX
 261#undef MEMSUFFIX
 262#endif /* (NB_MMU_MODES >= 6) */
 263
 264#if (NB_MMU_MODES >= 7) && defined(MMU_MODE6_SUFFIX)
 265
 266#define CPU_MMU_INDEX 6
 267#define MEMSUFFIX MMU_MODE6_SUFFIX
 268#define DATA_SIZE 1
 269#include "exec/cpu_ldst_template.h"
 270
 271#define DATA_SIZE 2
 272#include "exec/cpu_ldst_template.h"
 273
 274#define DATA_SIZE 4
 275#include "exec/cpu_ldst_template.h"
 276
 277#define DATA_SIZE 8
 278#include "exec/cpu_ldst_template.h"
 279#undef CPU_MMU_INDEX
 280#undef MEMSUFFIX
 281#endif /* (NB_MMU_MODES >= 7) */
 282
 283#if (NB_MMU_MODES >= 8) && defined(MMU_MODE7_SUFFIX)
 284
 285#define CPU_MMU_INDEX 7
 286#define MEMSUFFIX MMU_MODE7_SUFFIX
 287#define DATA_SIZE 1
 288#include "exec/cpu_ldst_template.h"
 289
 290#define DATA_SIZE 2
 291#include "exec/cpu_ldst_template.h"
 292
 293#define DATA_SIZE 4
 294#include "exec/cpu_ldst_template.h"
 295
 296#define DATA_SIZE 8
 297#include "exec/cpu_ldst_template.h"
 298#undef CPU_MMU_INDEX
 299#undef MEMSUFFIX
 300#endif /* (NB_MMU_MODES >= 8) */
 301
 302#if (NB_MMU_MODES >= 9) && defined(MMU_MODE8_SUFFIX)
 303
 304#define CPU_MMU_INDEX 8
 305#define MEMSUFFIX MMU_MODE8_SUFFIX
 306#define DATA_SIZE 1
 307#include "exec/cpu_ldst_template.h"
 308
 309#define DATA_SIZE 2
 310#include "exec/cpu_ldst_template.h"
 311
 312#define DATA_SIZE 4
 313#include "exec/cpu_ldst_template.h"
 314
 315#define DATA_SIZE 8
 316#include "exec/cpu_ldst_template.h"
 317#undef CPU_MMU_INDEX
 318#undef MEMSUFFIX
 319#endif /* (NB_MMU_MODES >= 9) */
 320
 321#if (NB_MMU_MODES >= 10) && defined(MMU_MODE9_SUFFIX)
 322
 323#define CPU_MMU_INDEX 9
 324#define MEMSUFFIX MMU_MODE9_SUFFIX
 325#define DATA_SIZE 1
 326#include "exec/cpu_ldst_template.h"
 327
 328#define DATA_SIZE 2
 329#include "exec/cpu_ldst_template.h"
 330
 331#define DATA_SIZE 4
 332#include "exec/cpu_ldst_template.h"
 333
 334#define DATA_SIZE 8
 335#include "exec/cpu_ldst_template.h"
 336#undef CPU_MMU_INDEX
 337#undef MEMSUFFIX
 338#endif /* (NB_MMU_MODES >= 10) */
 339
 340#if (NB_MMU_MODES >= 11) && defined(MMU_MODE10_SUFFIX)
 341
 342#define CPU_MMU_INDEX 10
 343#define MEMSUFFIX MMU_MODE10_SUFFIX
 344#define DATA_SIZE 1
 345#include "exec/cpu_ldst_template.h"
 346
 347#define DATA_SIZE 2
 348#include "exec/cpu_ldst_template.h"
 349
 350#define DATA_SIZE 4
 351#include "exec/cpu_ldst_template.h"
 352
 353#define DATA_SIZE 8
 354#include "exec/cpu_ldst_template.h"
 355#undef CPU_MMU_INDEX
 356#undef MEMSUFFIX
 357#endif /* (NB_MMU_MODES >= 11) */
 358
 359#if (NB_MMU_MODES >= 12) && defined(MMU_MODE11_SUFFIX)
 360
 361#define CPU_MMU_INDEX 11
 362#define MEMSUFFIX MMU_MODE11_SUFFIX
 363#define DATA_SIZE 1
 364#include "exec/cpu_ldst_template.h"
 365
 366#define DATA_SIZE 2
 367#include "exec/cpu_ldst_template.h"
 368
 369#define DATA_SIZE 4
 370#include "exec/cpu_ldst_template.h"
 371
 372#define DATA_SIZE 8
 373#include "exec/cpu_ldst_template.h"
 374#undef CPU_MMU_INDEX
 375#undef MEMSUFFIX
 376#endif /* (NB_MMU_MODES >= 12) */
 377
 378#if (NB_MMU_MODES > 12)
 379#error "NB_MMU_MODES > 12 is not supported for now"
 380#endif /* (NB_MMU_MODES > 12) */
 381
 382/* these access are slower, they must be as rare as possible */
 383#define CPU_MMU_INDEX (cpu_mmu_index(env, false))
 384#define MEMSUFFIX _data
 385#define DATA_SIZE 1
 386#include "exec/cpu_ldst_template.h"
 387
 388#define DATA_SIZE 2
 389#include "exec/cpu_ldst_template.h"
 390
 391#define DATA_SIZE 4
 392#include "exec/cpu_ldst_template.h"
 393
 394#define DATA_SIZE 8
 395#include "exec/cpu_ldst_template.h"
 396#undef CPU_MMU_INDEX
 397#undef MEMSUFFIX
 398
 399#define CPU_MMU_INDEX (cpu_mmu_index(env, true))
 400#define MEMSUFFIX _code
 401#define SOFTMMU_CODE_ACCESS
 402
 403#define DATA_SIZE 1
 404#include "exec/cpu_ldst_template.h"
 405
 406#define DATA_SIZE 2
 407#include "exec/cpu_ldst_template.h"
 408
 409#define DATA_SIZE 4
 410#include "exec/cpu_ldst_template.h"
 411
 412#define DATA_SIZE 8
 413#include "exec/cpu_ldst_template.h"
 414
 415#undef CPU_MMU_INDEX
 416#undef MEMSUFFIX
 417#undef SOFTMMU_CODE_ACCESS
 418
 419#endif /* defined(CONFIG_USER_ONLY) */
 420
 421/**
 422 * tlb_vaddr_to_host:
 423 * @env: CPUArchState
 424 * @addr: guest virtual address to look up
 425 * @access_type: 0 for read, 1 for write, 2 for execute
 426 * @mmu_idx: MMU index to use for lookup
 427 *
 428 * Look up the specified guest virtual index in the TCG softmmu TLB.
 429 * If the TLB contains a host virtual address suitable for direct RAM
 430 * access, then return it. Otherwise (TLB miss, TLB entry is for an
 431 * I/O access, etc) return NULL.
 432 *
 433 * This is the equivalent of the initial fast-path code used by
 434 * TCG backends for guest load and store accesses.
 435 */
 436static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
 437                                      int access_type, int mmu_idx)
 438{
 439#if defined(CONFIG_USER_ONLY)
 440    return g2h(addr);
 441#else
 442    CPUTLBEntry *tlbentry = tlb_entry(env, mmu_idx, addr);
 443    abi_ptr tlb_addr;
 444    uintptr_t haddr;
 445
 446    switch (access_type) {
 447    case 0:
 448        tlb_addr = tlbentry->addr_read;
 449        break;
 450    case 1:
 451        tlb_addr = tlb_addr_write(tlbentry);
 452        break;
 453    case 2:
 454        tlb_addr = tlbentry->addr_code;
 455        break;
 456    default:
 457        g_assert_not_reached();
 458    }
 459
 460    if (!tlb_hit(tlb_addr, addr)) {
 461        /* TLB entry is for a different page */
 462        return NULL;
 463    }
 464
 465    if (tlb_addr & ~TARGET_PAGE_MASK) {
 466        /* IO access */
 467        return NULL;
 468    }
 469
 470    haddr = addr + tlbentry->addend;
 471    return (void *)haddr;
 472#endif /* defined(CONFIG_USER_ONLY) */
 473}
 474
 475#endif /* CPU_LDST_H */
 476