[1] | 1 | /*
|
---|
| 2 | * defines common to all virtual CPUs
|
---|
[6532] | 3 | *
|
---|
[1] | 4 | * Copyright (c) 2003 Fabrice Bellard
|
---|
| 5 | *
|
---|
| 6 | * This library is free software; you can redistribute it and/or
|
---|
| 7 | * modify it under the terms of the GNU Lesser General Public
|
---|
| 8 | * License as published by the Free Software Foundation; either
|
---|
| 9 | * version 2 of the License, or (at your option) any later version.
|
---|
| 10 | *
|
---|
| 11 | * This library is distributed in the hope that it will be useful,
|
---|
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 14 | * Lesser General Public License for more details.
|
---|
| 15 | *
|
---|
| 16 | * You should have received a copy of the GNU Lesser General Public
|
---|
[36175] | 17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
---|
[1] | 18 | */
|
---|
[11982] | 19 |
|
---|
| 20 | /*
|
---|
[33656] | 21 | * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
|
---|
| 22 | * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
|
---|
[11982] | 23 | * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
|
---|
| 24 | * a choice of LGPL license versions is made available with the language indicating
|
---|
| 25 | * that LGPLv2 or any later version may be used, or where a choice of which version
|
---|
| 26 | * of the LGPL is applied is otherwise unspecified.
|
---|
| 27 | */
|
---|
[33656] | 28 |
|
---|
[1] | 29 | #ifndef CPU_ALL_H
|
---|
| 30 | #define CPU_ALL_H
|
---|
| 31 |
|
---|
[2422] | 32 | #ifdef VBOX
|
---|
| 33 | # ifndef LOG_GROUP
|
---|
| 34 | # define LOG_GROUP LOG_GROUP_REM
|
---|
| 35 | # endif
|
---|
[13382] | 36 | # include <VBox/log.h>
|
---|
[35346] | 37 | # include <VBox/vmm/pgm.h> /* PGM_DYNAMIC_RAM_ALLOC */
|
---|
[36170] | 38 | #endif /* VBOX */
|
---|
| 39 | #include "qemu-common.h"
|
---|
[36175] | 40 | #include "cpu-common.h"
|
---|
[2422] | 41 |
|
---|
[6532] | 42 | /* some important defines:
|
---|
| 43 | *
|
---|
[1] | 44 | * WORDS_ALIGNED : if defined, the host cpu can only make word aligned
|
---|
| 45 | * memory accesses.
|
---|
[6532] | 46 | *
|
---|
[37675] | 47 | * HOST_WORDS_BIGENDIAN : if defined, the host cpu is big endian and
|
---|
[1] | 48 | * otherwise little endian.
|
---|
[6532] | 49 | *
|
---|
[1] | 50 | * (TARGET_WORDS_ALIGNED : same for target cpu (not supported yet))
|
---|
[6532] | 51 | *
|
---|
[1] | 52 | * TARGET_WORDS_BIGENDIAN : same for target cpu
|
---|
| 53 | */
|
---|
| 54 |
|
---|
[36140] | 55 | #include "softfloat.h"
|
---|
[1] | 56 |
|
---|
[37675] | 57 | #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
---|
[1] | 58 | #define BSWAP_NEEDED
|
---|
| 59 | #endif
|
---|
| 60 |
|
---|
| 61 | #ifdef BSWAP_NEEDED
|
---|
| 62 |
|
---|
| 63 | static inline uint16_t tswap16(uint16_t s)
|
---|
| 64 | {
|
---|
| 65 | return bswap16(s);
|
---|
| 66 | }
|
---|
| 67 |
|
---|
| 68 | static inline uint32_t tswap32(uint32_t s)
|
---|
| 69 | {
|
---|
| 70 | return bswap32(s);
|
---|
| 71 | }
|
---|
| 72 |
|
---|
| 73 | static inline uint64_t tswap64(uint64_t s)
|
---|
| 74 | {
|
---|
| 75 | return bswap64(s);
|
---|
| 76 | }
|
---|
| 77 |
|
---|
| 78 | static inline void tswap16s(uint16_t *s)
|
---|
| 79 | {
|
---|
| 80 | *s = bswap16(*s);
|
---|
| 81 | }
|
---|
| 82 |
|
---|
| 83 | static inline void tswap32s(uint32_t *s)
|
---|
| 84 | {
|
---|
| 85 | *s = bswap32(*s);
|
---|
| 86 | }
|
---|
| 87 |
|
---|
| 88 | static inline void tswap64s(uint64_t *s)
|
---|
| 89 | {
|
---|
| 90 | *s = bswap64(*s);
|
---|
| 91 | }
|
---|
| 92 |
|
---|
| 93 | #else
|
---|
| 94 |
|
---|
| 95 | static inline uint16_t tswap16(uint16_t s)
|
---|
| 96 | {
|
---|
| 97 | return s;
|
---|
| 98 | }
|
---|
| 99 |
|
---|
| 100 | static inline uint32_t tswap32(uint32_t s)
|
---|
| 101 | {
|
---|
| 102 | return s;
|
---|
| 103 | }
|
---|
| 104 |
|
---|
| 105 | static inline uint64_t tswap64(uint64_t s)
|
---|
| 106 | {
|
---|
| 107 | return s;
|
---|
| 108 | }
|
---|
| 109 |
|
---|
| 110 | static inline void tswap16s(uint16_t *s)
|
---|
| 111 | {
|
---|
| 112 | }
|
---|
| 113 |
|
---|
| 114 | static inline void tswap32s(uint32_t *s)
|
---|
| 115 | {
|
---|
| 116 | }
|
---|
| 117 |
|
---|
| 118 | static inline void tswap64s(uint64_t *s)
|
---|
| 119 | {
|
---|
| 120 | }
|
---|
| 121 |
|
---|
| 122 | #endif
|
---|
| 123 |
|
---|
| 124 | #if TARGET_LONG_SIZE == 4
|
---|
| 125 | #define tswapl(s) tswap32(s)
|
---|
| 126 | #define tswapls(s) tswap32s((uint32_t *)(s))
|
---|
[2422] | 127 | #define bswaptls(s) bswap32s(s)
|
---|
[1] | 128 | #else
|
---|
| 129 | #define tswapl(s) tswap64(s)
|
---|
| 130 | #define tswapls(s) tswap64s((uint64_t *)(s))
|
---|
[2422] | 131 | #define bswaptls(s) bswap64s(s)
|
---|
[1] | 132 | #endif
|
---|
| 133 |
|
---|
[13230] | 134 | typedef union {
|
---|
| 135 | float32 f;
|
---|
| 136 | uint32_t l;
|
---|
| 137 | } CPU_FloatU;
|
---|
| 138 |
|
---|
[1] | 139 | /* NOTE: arm FPA is horrible as double 32 bit words are stored in big
|
---|
| 140 | endian ! */
|
---|
| 141 | typedef union {
|
---|
[2422] | 142 | float64 d;
|
---|
[37675] | 143 | #if defined(HOST_WORDS_BIGENDIAN) \
|
---|
[2422] | 144 | || (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
|
---|
[1] | 145 | struct {
|
---|
| 146 | uint32_t upper;
|
---|
| 147 | uint32_t lower;
|
---|
| 148 | } l;
|
---|
| 149 | #else
|
---|
| 150 | struct {
|
---|
| 151 | uint32_t lower;
|
---|
| 152 | uint32_t upper;
|
---|
| 153 | } l;
|
---|
| 154 | #endif
|
---|
| 155 | uint64_t ll;
|
---|
| 156 | } CPU_DoubleU;
|
---|
| 157 |
|
---|
[13230] | 158 | #ifdef TARGET_SPARC
|
---|
| 159 | typedef union {
|
---|
| 160 | float128 q;
|
---|
[37675] | 161 | #if defined(HOST_WORDS_BIGENDIAN) \
|
---|
[13230] | 162 | || (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
|
---|
| 163 | struct {
|
---|
| 164 | uint32_t upmost;
|
---|
| 165 | uint32_t upper;
|
---|
| 166 | uint32_t lower;
|
---|
| 167 | uint32_t lowest;
|
---|
| 168 | } l;
|
---|
| 169 | struct {
|
---|
| 170 | uint64_t upper;
|
---|
| 171 | uint64_t lower;
|
---|
| 172 | } ll;
|
---|
| 173 | #else
|
---|
| 174 | struct {
|
---|
| 175 | uint32_t lowest;
|
---|
| 176 | uint32_t lower;
|
---|
| 177 | uint32_t upper;
|
---|
| 178 | uint32_t upmost;
|
---|
| 179 | } l;
|
---|
| 180 | struct {
|
---|
| 181 | uint64_t lower;
|
---|
| 182 | uint64_t upper;
|
---|
| 183 | } ll;
|
---|
| 184 | #endif
|
---|
| 185 | } CPU_QuadU;
|
---|
| 186 | #endif
|
---|
| 187 |
|
---|
[1] | 188 | /* CPU memory access without any memory or io remapping */
|
---|
| 189 |
|
---|
| 190 | /*
|
---|
| 191 | * the generic syntax for the memory accesses is:
|
---|
| 192 | *
|
---|
| 193 | * load: ld{type}{sign}{size}{endian}_{access_type}(ptr)
|
---|
| 194 | *
|
---|
| 195 | * store: st{type}{size}{endian}_{access_type}(ptr, val)
|
---|
| 196 | *
|
---|
| 197 | * type is:
|
---|
| 198 | * (empty): integer access
|
---|
| 199 | * f : float access
|
---|
[6532] | 200 | *
|
---|
[1] | 201 | * sign is:
|
---|
| 202 | * (empty): for floats or 32 bit size
|
---|
| 203 | * u : unsigned
|
---|
| 204 | * s : signed
|
---|
| 205 | *
|
---|
| 206 | * size is:
|
---|
| 207 | * b: 8 bits
|
---|
| 208 | * w: 16 bits
|
---|
| 209 | * l: 32 bits
|
---|
| 210 | * q: 64 bits
|
---|
[6532] | 211 | *
|
---|
[1] | 212 | * endian is:
|
---|
| 213 | * (empty): target cpu endianness or 8 bit access
|
---|
| 214 | * r : reversed target cpu endianness (not implemented yet)
|
---|
| 215 | * be : big endian (not implemented yet)
|
---|
| 216 | * le : little endian (not implemented yet)
|
---|
| 217 | *
|
---|
| 218 | * access_type is:
|
---|
| 219 | * raw : host memory access
|
---|
| 220 | * user : user mode access using soft MMU
|
---|
| 221 | * kernel : kernel mode access using soft MMU
|
---|
| 222 | */
|
---|
[14277] | 223 |
|
---|
[1] | 224 | #ifdef VBOX
|
---|
[18662] | 225 | void remAbort(int rc, const char *pszTip) __attribute__((__noreturn__));
|
---|
[14475] | 226 |
|
---|
[14962] | 227 | void remR3PhysRead(RTGCPHYS SrcGCPhys, void *pvDst, unsigned cb);
|
---|
| 228 | RTCCUINTREG remR3PhysReadU8(RTGCPHYS SrcGCPhys);
|
---|
| 229 | RTCCINTREG remR3PhysReadS8(RTGCPHYS SrcGCPhys);
|
---|
| 230 | RTCCUINTREG remR3PhysReadU16(RTGCPHYS SrcGCPhys);
|
---|
| 231 | RTCCINTREG remR3PhysReadS16(RTGCPHYS SrcGCPhys);
|
---|
| 232 | RTCCUINTREG remR3PhysReadU32(RTGCPHYS SrcGCPhys);
|
---|
| 233 | RTCCINTREG remR3PhysReadS32(RTGCPHYS SrcGCPhys);
|
---|
| 234 | uint64_t remR3PhysReadU64(RTGCPHYS SrcGCPhys);
|
---|
| 235 | int64_t remR3PhysReadS64(RTGCPHYS SrcGCPhys);
|
---|
[15284] | 236 | void remR3PhysWrite(RTGCPHYS DstGCPhys, const void *pvSrc, unsigned cb);
|
---|
| 237 | void remR3PhysWriteU8(RTGCPHYS DstGCPhys, uint8_t val);
|
---|
| 238 | void remR3PhysWriteU16(RTGCPHYS DstGCPhys, uint16_t val);
|
---|
| 239 | void remR3PhysWriteU32(RTGCPHYS DstGCPhys, uint32_t val);
|
---|
| 240 | void remR3PhysWriteU64(RTGCPHYS DstGCPhys, uint64_t val);
|
---|
[2422] | 241 |
|
---|
[37675] | 242 | # ifndef REM_PHYS_ADDR_IN_TLB
|
---|
[15284] | 243 | void *remR3TlbGCPhys2Ptr(CPUState *env1, target_ulong physAddr, int fWritable);
|
---|
[37675] | 244 | # endif
|
---|
[1] | 245 |
|
---|
[14277] | 246 | #endif /* VBOX */
|
---|
| 247 |
|
---|
| 248 | #if defined(VBOX) && defined(REM_PHYS_ADDR_IN_TLB)
|
---|
| 249 |
|
---|
[36170] | 250 | DECLINLINE(uint8_t) ldub_p(const void *ptr)
|
---|
[1] | 251 | {
|
---|
[2422] | 252 | VBOX_CHECK_ADDR(ptr);
|
---|
| 253 | return remR3PhysReadU8((uintptr_t)ptr);
|
---|
[1] | 254 | }
|
---|
| 255 |
|
---|
[36170] | 256 | DECLINLINE(int8_t) ldsb_p(const void *ptr)
|
---|
[1] | 257 | {
|
---|
[2422] | 258 | VBOX_CHECK_ADDR(ptr);
|
---|
| 259 | return remR3PhysReadS8((uintptr_t)ptr);
|
---|
[1] | 260 | }
|
---|
| 261 |
|
---|
[13382] | 262 | DECLINLINE(void) stb_p(void *ptr, int v)
|
---|
[1] | 263 | {
|
---|
[2422] | 264 | VBOX_CHECK_ADDR(ptr);
|
---|
| 265 | remR3PhysWriteU8((uintptr_t)ptr, v);
|
---|
[1] | 266 | }
|
---|
| 267 |
|
---|
[36170] | 268 | DECLINLINE(uint32_t) lduw_le_p(const void *ptr)
|
---|
[2422] | 269 | {
|
---|
| 270 | VBOX_CHECK_ADDR(ptr);
|
---|
| 271 | return remR3PhysReadU16((uintptr_t)ptr);
|
---|
| 272 | }
|
---|
| 273 |
|
---|
[36170] | 274 | DECLINLINE(int32_t) ldsw_le_p(const void *ptr)
|
---|
[2422] | 275 | {
|
---|
| 276 | VBOX_CHECK_ADDR(ptr);
|
---|
| 277 | return remR3PhysReadS16((uintptr_t)ptr);
|
---|
| 278 | }
|
---|
| 279 |
|
---|
[13382] | 280 | DECLINLINE(void) stw_le_p(void *ptr, int v)
|
---|
[2422] | 281 | {
|
---|
| 282 | VBOX_CHECK_ADDR(ptr);
|
---|
| 283 | remR3PhysWriteU16((uintptr_t)ptr, v);
|
---|
| 284 | }
|
---|
| 285 |
|
---|
[36170] | 286 | DECLINLINE(uint32_t) ldl_le_p(const void *ptr)
|
---|
[2422] | 287 | {
|
---|
| 288 | VBOX_CHECK_ADDR(ptr);
|
---|
| 289 | return remR3PhysReadU32((uintptr_t)ptr);
|
---|
| 290 | }
|
---|
| 291 |
|
---|
[13382] | 292 | DECLINLINE(void) stl_le_p(void *ptr, int v)
|
---|
[2422] | 293 | {
|
---|
| 294 | VBOX_CHECK_ADDR(ptr);
|
---|
| 295 | remR3PhysWriteU32((uintptr_t)ptr, v);
|
---|
| 296 | }
|
---|
| 297 |
|
---|
[13382] | 298 | DECLINLINE(void) stq_le_p(void *ptr, uint64_t v)
|
---|
[2422] | 299 | {
|
---|
| 300 | VBOX_CHECK_ADDR(ptr);
|
---|
| 301 | remR3PhysWriteU64((uintptr_t)ptr, v);
|
---|
| 302 | }
|
---|
| 303 |
|
---|
[36170] | 304 | DECLINLINE(uint64_t) ldq_le_p(const void *ptr)
|
---|
[2422] | 305 | {
|
---|
| 306 | VBOX_CHECK_ADDR(ptr);
|
---|
| 307 | return remR3PhysReadU64((uintptr_t)ptr);
|
---|
| 308 | }
|
---|
| 309 |
|
---|
[37675] | 310 | # undef VBOX_CHECK_ADDR
|
---|
[2422] | 311 |
|
---|
| 312 | /* float access */
|
---|
| 313 |
|
---|
[36170] | 314 | DECLINLINE(float32) ldfl_le_p(const void *ptr)
|
---|
[2422] | 315 | {
|
---|
| 316 | union {
|
---|
| 317 | float32 f;
|
---|
| 318 | uint32_t i;
|
---|
| 319 | } u;
|
---|
| 320 | u.i = ldl_le_p(ptr);
|
---|
| 321 | return u.f;
|
---|
| 322 | }
|
---|
| 323 |
|
---|
[13382] | 324 | DECLINLINE(void) stfl_le_p(void *ptr, float32 v)
|
---|
[2422] | 325 | {
|
---|
| 326 | union {
|
---|
| 327 | float32 f;
|
---|
| 328 | uint32_t i;
|
---|
| 329 | } u;
|
---|
| 330 | u.f = v;
|
---|
| 331 | stl_le_p(ptr, u.i);
|
---|
| 332 | }
|
---|
| 333 |
|
---|
[36170] | 334 | DECLINLINE(float64) ldfq_le_p(const void *ptr)
|
---|
[2422] | 335 | {
|
---|
| 336 | CPU_DoubleU u;
|
---|
| 337 | u.l.lower = ldl_le_p(ptr);
|
---|
[13382] | 338 | u.l.upper = ldl_le_p((uint8_t*)ptr + 4);
|
---|
[2422] | 339 | return u.d;
|
---|
| 340 | }
|
---|
| 341 |
|
---|
[13382] | 342 | DECLINLINE(void) stfq_le_p(void *ptr, float64 v)
|
---|
[2422] | 343 | {
|
---|
| 344 | CPU_DoubleU u;
|
---|
| 345 | u.d = v;
|
---|
| 346 | stl_le_p(ptr, u.l.lower);
|
---|
[13382] | 347 | stl_le_p((uint8_t*)ptr + 4, u.l.upper);
|
---|
[2422] | 348 | }
|
---|
| 349 |
|
---|
[37689] | 350 | #else /* !VBOX || !REM_PHYS_ADDR_IN_TLB */
|
---|
[2422] | 351 |
|
---|
[36170] | 352 | static inline int ldub_p(const void *ptr)
|
---|
[1] | 353 | {
|
---|
| 354 | return *(uint8_t *)ptr;
|
---|
| 355 | }
|
---|
| 356 |
|
---|
[36170] | 357 | static inline int ldsb_p(const void *ptr)
|
---|
[1] | 358 | {
|
---|
| 359 | return *(int8_t *)ptr;
|
---|
| 360 | }
|
---|
| 361 |
|
---|
| 362 | static inline void stb_p(void *ptr, int v)
|
---|
| 363 | {
|
---|
| 364 | *(uint8_t *)ptr = v;
|
---|
| 365 | }
|
---|
| 366 |
|
---|
| 367 | /* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
|
---|
| 368 | kernel handles unaligned load/stores may give better results, but
|
---|
| 369 | it is a system wide setting : bad */
|
---|
[37675] | 370 | #if defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
|
---|
[2422] | 371 |
|
---|
[1] | 372 | /* conservative code for little endian unaligned accesses */
|
---|
[36170] | 373 | static inline int lduw_le_p(const void *ptr)
|
---|
[1] | 374 | {
|
---|
[36170] | 375 | #ifdef _ARCH_PPC
|
---|
[1] | 376 | int val;
|
---|
| 377 | __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
|
---|
| 378 | return val;
|
---|
| 379 | #else
|
---|
[36170] | 380 | const uint8_t *p = ptr;
|
---|
[1] | 381 | return p[0] | (p[1] << 8);
|
---|
| 382 | #endif
|
---|
| 383 | }
|
---|
| 384 |
|
---|
[36170] | 385 | static inline int ldsw_le_p(const void *ptr)
|
---|
[1] | 386 | {
|
---|
[36170] | 387 | #ifdef _ARCH_PPC
|
---|
[1] | 388 | int val;
|
---|
| 389 | __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
|
---|
| 390 | return (int16_t)val;
|
---|
| 391 | #else
|
---|
[36170] | 392 | const uint8_t *p = ptr;
|
---|
[1] | 393 | return (int16_t)(p[0] | (p[1] << 8));
|
---|
| 394 | #endif
|
---|
| 395 | }
|
---|
| 396 |
|
---|
[36170] | 397 | static inline int ldl_le_p(const void *ptr)
|
---|
[1] | 398 | {
|
---|
[36170] | 399 | #ifdef _ARCH_PPC
|
---|
[1] | 400 | int val;
|
---|
| 401 | __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
|
---|
| 402 | return val;
|
---|
| 403 | #else
|
---|
[36170] | 404 | const uint8_t *p = ptr;
|
---|
[1] | 405 | return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
|
---|
| 406 | #endif
|
---|
| 407 | }
|
---|
| 408 |
|
---|
[36170] | 409 | static inline uint64_t ldq_le_p(const void *ptr)
|
---|
[1] | 410 | {
|
---|
[36170] | 411 | const uint8_t *p = ptr;
|
---|
[1] | 412 | uint32_t v1, v2;
|
---|
[2422] | 413 | v1 = ldl_le_p(p);
|
---|
| 414 | v2 = ldl_le_p(p + 4);
|
---|
[1] | 415 | return v1 | ((uint64_t)v2 << 32);
|
---|
| 416 | }
|
---|
| 417 |
|
---|
[2422] | 418 | static inline void stw_le_p(void *ptr, int v)
|
---|
[1] | 419 | {
|
---|
[36170] | 420 | #ifdef _ARCH_PPC
|
---|
[1] | 421 | __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
|
---|
| 422 | #else
|
---|
| 423 | uint8_t *p = ptr;
|
---|
| 424 | p[0] = v;
|
---|
| 425 | p[1] = v >> 8;
|
---|
| 426 | #endif
|
---|
| 427 | }
|
---|
| 428 |
|
---|
[2422] | 429 | static inline void stl_le_p(void *ptr, int v)
|
---|
[1] | 430 | {
|
---|
[36170] | 431 | #ifdef _ARCH_PPC
|
---|
[1] | 432 | __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
|
---|
| 433 | #else
|
---|
| 434 | uint8_t *p = ptr;
|
---|
| 435 | p[0] = v;
|
---|
| 436 | p[1] = v >> 8;
|
---|
| 437 | p[2] = v >> 16;
|
---|
| 438 | p[3] = v >> 24;
|
---|
| 439 | #endif
|
---|
| 440 | }
|
---|
| 441 |
|
---|
[2422] | 442 | static inline void stq_le_p(void *ptr, uint64_t v)
|
---|
[1] | 443 | {
|
---|
| 444 | uint8_t *p = ptr;
|
---|
[2422] | 445 | stl_le_p(p, (uint32_t)v);
|
---|
| 446 | stl_le_p(p + 4, v >> 32);
|
---|
[1] | 447 | }
|
---|
| 448 |
|
---|
| 449 | /* float access */
|
---|
| 450 |
|
---|
[36170] | 451 | static inline float32 ldfl_le_p(const void *ptr)
|
---|
[1] | 452 | {
|
---|
| 453 | union {
|
---|
[2422] | 454 | float32 f;
|
---|
[1] | 455 | uint32_t i;
|
---|
| 456 | } u;
|
---|
[2422] | 457 | u.i = ldl_le_p(ptr);
|
---|
[1] | 458 | return u.f;
|
---|
| 459 | }
|
---|
| 460 |
|
---|
[2422] | 461 | static inline void stfl_le_p(void *ptr, float32 v)
|
---|
[1] | 462 | {
|
---|
| 463 | union {
|
---|
[2422] | 464 | float32 f;
|
---|
[1] | 465 | uint32_t i;
|
---|
| 466 | } u;
|
---|
| 467 | u.f = v;
|
---|
[2422] | 468 | stl_le_p(ptr, u.i);
|
---|
[1] | 469 | }
|
---|
| 470 |
|
---|
[36170] | 471 | static inline float64 ldfq_le_p(const void *ptr)
|
---|
[1] | 472 | {
|
---|
| 473 | CPU_DoubleU u;
|
---|
[2422] | 474 | u.l.lower = ldl_le_p(ptr);
|
---|
| 475 | u.l.upper = ldl_le_p(ptr + 4);
|
---|
[1] | 476 | return u.d;
|
---|
| 477 | }
|
---|
| 478 |
|
---|
[2422] | 479 | static inline void stfq_le_p(void *ptr, float64 v)
|
---|
[1] | 480 | {
|
---|
| 481 | CPU_DoubleU u;
|
---|
| 482 | u.d = v;
|
---|
[2422] | 483 | stl_le_p(ptr, u.l.lower);
|
---|
| 484 | stl_le_p(ptr + 4, u.l.upper);
|
---|
[1] | 485 | }
|
---|
| 486 |
|
---|
[2422] | 487 | #else
|
---|
| 488 |
|
---|
[36170] | 489 | static inline int lduw_le_p(const void *ptr)
|
---|
[1] | 490 | {
|
---|
[2422] | 491 | return *(uint16_t *)ptr;
|
---|
| 492 | }
|
---|
| 493 |
|
---|
[36170] | 494 | static inline int ldsw_le_p(const void *ptr)
|
---|
[2422] | 495 | {
|
---|
| 496 | return *(int16_t *)ptr;
|
---|
| 497 | }
|
---|
| 498 |
|
---|
[36170] | 499 | static inline int ldl_le_p(const void *ptr)
|
---|
[2422] | 500 | {
|
---|
| 501 | return *(uint32_t *)ptr;
|
---|
| 502 | }
|
---|
| 503 |
|
---|
[36170] | 504 | static inline uint64_t ldq_le_p(const void *ptr)
|
---|
[2422] | 505 | {
|
---|
| 506 | return *(uint64_t *)ptr;
|
---|
| 507 | }
|
---|
| 508 |
|
---|
| 509 | static inline void stw_le_p(void *ptr, int v)
|
---|
| 510 | {
|
---|
| 511 | *(uint16_t *)ptr = v;
|
---|
| 512 | }
|
---|
| 513 |
|
---|
| 514 | static inline void stl_le_p(void *ptr, int v)
|
---|
| 515 | {
|
---|
| 516 | *(uint32_t *)ptr = v;
|
---|
| 517 | }
|
---|
| 518 |
|
---|
| 519 | static inline void stq_le_p(void *ptr, uint64_t v)
|
---|
| 520 | {
|
---|
| 521 | *(uint64_t *)ptr = v;
|
---|
| 522 | }
|
---|
| 523 |
|
---|
| 524 | /* float access */
|
---|
| 525 |
|
---|
[36170] | 526 | static inline float32 ldfl_le_p(const void *ptr)
|
---|
[2422] | 527 | {
|
---|
| 528 | return *(float32 *)ptr;
|
---|
| 529 | }
|
---|
| 530 |
|
---|
[36170] | 531 | static inline float64 ldfq_le_p(const void *ptr)
|
---|
[2422] | 532 | {
|
---|
| 533 | return *(float64 *)ptr;
|
---|
| 534 | }
|
---|
| 535 |
|
---|
| 536 | static inline void stfl_le_p(void *ptr, float32 v)
|
---|
| 537 | {
|
---|
| 538 | *(float32 *)ptr = v;
|
---|
| 539 | }
|
---|
| 540 |
|
---|
| 541 | static inline void stfq_le_p(void *ptr, float64 v)
|
---|
| 542 | {
|
---|
| 543 | *(float64 *)ptr = v;
|
---|
| 544 | }
|
---|
| 545 | #endif
|
---|
| 546 |
|
---|
[37689] | 547 | #endif /* !VBOX || !REM_PHYS_ADDR_IN_TLB */
|
---|
| 548 |
|
---|
[37675] | 549 | #if !defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
|
---|
[2422] | 550 |
|
---|
[36170] | 551 | static inline int lduw_be_p(const void *ptr)
|
---|
[2422] | 552 | {
|
---|
[1] | 553 | #if defined(__i386__)
|
---|
| 554 | int val;
|
---|
| 555 | asm volatile ("movzwl %1, %0\n"
|
---|
| 556 | "xchgb %b0, %h0\n"
|
---|
| 557 | : "=q" (val)
|
---|
| 558 | : "m" (*(uint16_t *)ptr));
|
---|
| 559 | return val;
|
---|
| 560 | #else
|
---|
[36170] | 561 | const uint8_t *b = ptr;
|
---|
[1] | 562 | return ((b[0] << 8) | b[1]);
|
---|
| 563 | #endif
|
---|
| 564 | }
|
---|
| 565 |
|
---|
[36170] | 566 | static inline int ldsw_be_p(const void *ptr)
|
---|
[1] | 567 | {
|
---|
| 568 | #if defined(__i386__)
|
---|
| 569 | int val;
|
---|
| 570 | asm volatile ("movzwl %1, %0\n"
|
---|
| 571 | "xchgb %b0, %h0\n"
|
---|
| 572 | : "=q" (val)
|
---|
| 573 | : "m" (*(uint16_t *)ptr));
|
---|
| 574 | return (int16_t)val;
|
---|
| 575 | #else
|
---|
[36170] | 576 | const uint8_t *b = ptr;
|
---|
[1] | 577 | return (int16_t)((b[0] << 8) | b[1]);
|
---|
| 578 | #endif
|
---|
| 579 | }
|
---|
| 580 |
|
---|
[36170] | 581 | static inline int ldl_be_p(const void *ptr)
|
---|
[1] | 582 | {
|
---|
| 583 | #if defined(__i386__) || defined(__x86_64__)
|
---|
| 584 | int val;
|
---|
| 585 | asm volatile ("movl %1, %0\n"
|
---|
| 586 | "bswap %0\n"
|
---|
| 587 | : "=r" (val)
|
---|
| 588 | : "m" (*(uint32_t *)ptr));
|
---|
| 589 | return val;
|
---|
| 590 | #else
|
---|
[36170] | 591 | const uint8_t *b = ptr;
|
---|
[1] | 592 | return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
|
---|
| 593 | #endif
|
---|
| 594 | }
|
---|
| 595 |
|
---|
[36170] | 596 | static inline uint64_t ldq_be_p(const void *ptr)
|
---|
[1] | 597 | {
|
---|
| 598 | uint32_t a,b;
|
---|
[2422] | 599 | a = ldl_be_p(ptr);
|
---|
[36140] | 600 | b = ldl_be_p((uint8_t *)ptr + 4);
|
---|
[1] | 601 | return (((uint64_t)a<<32)|b);
|
---|
| 602 | }
|
---|
| 603 |
|
---|
[2422] | 604 | static inline void stw_be_p(void *ptr, int v)
|
---|
[1] | 605 | {
|
---|
| 606 | #if defined(__i386__)
|
---|
| 607 | asm volatile ("xchgb %b0, %h0\n"
|
---|
| 608 | "movw %w0, %1\n"
|
---|
| 609 | : "=q" (v)
|
---|
| 610 | : "m" (*(uint16_t *)ptr), "0" (v));
|
---|
| 611 | #else
|
---|
| 612 | uint8_t *d = (uint8_t *) ptr;
|
---|
| 613 | d[0] = v >> 8;
|
---|
| 614 | d[1] = v;
|
---|
| 615 | #endif
|
---|
| 616 | }
|
---|
| 617 |
|
---|
[2422] | 618 | static inline void stl_be_p(void *ptr, int v)
|
---|
[1] | 619 | {
|
---|
| 620 | #if defined(__i386__) || defined(__x86_64__)
|
---|
| 621 | asm volatile ("bswap %0\n"
|
---|
| 622 | "movl %0, %1\n"
|
---|
| 623 | : "=r" (v)
|
---|
| 624 | : "m" (*(uint32_t *)ptr), "0" (v));
|
---|
| 625 | #else
|
---|
| 626 | uint8_t *d = (uint8_t *) ptr;
|
---|
| 627 | d[0] = v >> 24;
|
---|
| 628 | d[1] = v >> 16;
|
---|
| 629 | d[2] = v >> 8;
|
---|
| 630 | d[3] = v;
|
---|
| 631 | #endif
|
---|
| 632 | }
|
---|
| 633 |
|
---|
[2422] | 634 | static inline void stq_be_p(void *ptr, uint64_t v)
|
---|
[1] | 635 | {
|
---|
[2422] | 636 | stl_be_p(ptr, v >> 32);
|
---|
[36140] | 637 | stl_be_p((uint8_t *)ptr + 4, v);
|
---|
[1] | 638 | }
|
---|
| 639 |
|
---|
| 640 | /* float access */
|
---|
[36140] | 641 |
|
---|
[36170] | 642 | static inline float32 ldfl_be_p(const void *ptr)
|
---|
[1] | 643 | {
|
---|
| 644 | union {
|
---|
[2422] | 645 | float32 f;
|
---|
[1] | 646 | uint32_t i;
|
---|
| 647 | } u;
|
---|
[2422] | 648 | u.i = ldl_be_p(ptr);
|
---|
[1] | 649 | return u.f;
|
---|
| 650 | }
|
---|
| 651 |
|
---|
[2422] | 652 | static inline void stfl_be_p(void *ptr, float32 v)
|
---|
[1] | 653 | {
|
---|
| 654 | union {
|
---|
[2422] | 655 | float32 f;
|
---|
[1] | 656 | uint32_t i;
|
---|
| 657 | } u;
|
---|
| 658 | u.f = v;
|
---|
[2422] | 659 | stl_be_p(ptr, u.i);
|
---|
[1] | 660 | }
|
---|
| 661 |
|
---|
[36170] | 662 | static inline float64 ldfq_be_p(const void *ptr)
|
---|
[1] | 663 | {
|
---|
| 664 | CPU_DoubleU u;
|
---|
[2422] | 665 | u.l.upper = ldl_be_p(ptr);
|
---|
[36140] | 666 | u.l.lower = ldl_be_p((uint8_t *)ptr + 4);
|
---|
[1] | 667 | return u.d;
|
---|
| 668 | }
|
---|
| 669 |
|
---|
[2422] | 670 | static inline void stfq_be_p(void *ptr, float64 v)
|
---|
[1] | 671 | {
|
---|
| 672 | CPU_DoubleU u;
|
---|
| 673 | u.d = v;
|
---|
[2422] | 674 | stl_be_p(ptr, u.l.upper);
|
---|
[36140] | 675 | stl_be_p((uint8_t *)ptr + 4, u.l.lower);
|
---|
[1] | 676 | }
|
---|
| 677 |
|
---|
| 678 | #else
|
---|
| 679 |
|
---|
[36170] | 680 | static inline int lduw_be_p(const void *ptr)
|
---|
[1] | 681 | {
|
---|
| 682 | return *(uint16_t *)ptr;
|
---|
| 683 | }
|
---|
| 684 |
|
---|
[36170] | 685 | static inline int ldsw_be_p(const void *ptr)
|
---|
[1] | 686 | {
|
---|
| 687 | return *(int16_t *)ptr;
|
---|
| 688 | }
|
---|
| 689 |
|
---|
[36170] | 690 | static inline int ldl_be_p(const void *ptr)
|
---|
[1] | 691 | {
|
---|
| 692 | return *(uint32_t *)ptr;
|
---|
| 693 | }
|
---|
| 694 |
|
---|
[36170] | 695 | static inline uint64_t ldq_be_p(const void *ptr)
|
---|
[1] | 696 | {
|
---|
| 697 | return *(uint64_t *)ptr;
|
---|
| 698 | }
|
---|
| 699 |
|
---|
[2422] | 700 | static inline void stw_be_p(void *ptr, int v)
|
---|
[1] | 701 | {
|
---|
| 702 | *(uint16_t *)ptr = v;
|
---|
| 703 | }
|
---|
| 704 |
|
---|
[2422] | 705 | static inline void stl_be_p(void *ptr, int v)
|
---|
[1] | 706 | {
|
---|
| 707 | *(uint32_t *)ptr = v;
|
---|
| 708 | }
|
---|
| 709 |
|
---|
[2422] | 710 | static inline void stq_be_p(void *ptr, uint64_t v)
|
---|
[1] | 711 | {
|
---|
| 712 | *(uint64_t *)ptr = v;
|
---|
| 713 | }
|
---|
| 714 |
|
---|
| 715 | /* float access */
|
---|
| 716 |
|
---|
[36170] | 717 | static inline float32 ldfl_be_p(const void *ptr)
|
---|
[1] | 718 | {
|
---|
[2422] | 719 | return *(float32 *)ptr;
|
---|
[1] | 720 | }
|
---|
| 721 |
|
---|
[36170] | 722 | static inline float64 ldfq_be_p(const void *ptr)
|
---|
[1] | 723 | {
|
---|
[2422] | 724 | return *(float64 *)ptr;
|
---|
[1] | 725 | }
|
---|
| 726 |
|
---|
[2422] | 727 | static inline void stfl_be_p(void *ptr, float32 v)
|
---|
[1] | 728 | {
|
---|
[2422] | 729 | *(float32 *)ptr = v;
|
---|
[1] | 730 | }
|
---|
| 731 |
|
---|
[2422] | 732 | static inline void stfq_be_p(void *ptr, float64 v)
|
---|
[1] | 733 | {
|
---|
[2422] | 734 | *(float64 *)ptr = v;
|
---|
[1] | 735 | }
|
---|
| 736 |
|
---|
| 737 | #endif
|
---|
| 738 |
|
---|
[2422] | 739 | /* target CPU memory access functions */
|
---|
| 740 | #if defined(TARGET_WORDS_BIGENDIAN)
|
---|
| 741 | #define lduw_p(p) lduw_be_p(p)
|
---|
| 742 | #define ldsw_p(p) ldsw_be_p(p)
|
---|
| 743 | #define ldl_p(p) ldl_be_p(p)
|
---|
| 744 | #define ldq_p(p) ldq_be_p(p)
|
---|
| 745 | #define ldfl_p(p) ldfl_be_p(p)
|
---|
| 746 | #define ldfq_p(p) ldfq_be_p(p)
|
---|
| 747 | #define stw_p(p, v) stw_be_p(p, v)
|
---|
| 748 | #define stl_p(p, v) stl_be_p(p, v)
|
---|
| 749 | #define stq_p(p, v) stq_be_p(p, v)
|
---|
| 750 | #define stfl_p(p, v) stfl_be_p(p, v)
|
---|
| 751 | #define stfq_p(p, v) stfq_be_p(p, v)
|
---|
| 752 | #else
|
---|
| 753 | #define lduw_p(p) lduw_le_p(p)
|
---|
| 754 | #define ldsw_p(p) ldsw_le_p(p)
|
---|
| 755 | #define ldl_p(p) ldl_le_p(p)
|
---|
| 756 | #define ldq_p(p) ldq_le_p(p)
|
---|
| 757 | #define ldfl_p(p) ldfl_le_p(p)
|
---|
| 758 | #define ldfq_p(p) ldfq_le_p(p)
|
---|
| 759 | #define stw_p(p, v) stw_le_p(p, v)
|
---|
| 760 | #define stl_p(p, v) stl_le_p(p, v)
|
---|
| 761 | #define stq_p(p, v) stq_le_p(p, v)
|
---|
| 762 | #define stfl_p(p, v) stfl_le_p(p, v)
|
---|
| 763 | #define stfq_p(p, v) stfq_le_p(p, v)
|
---|
| 764 | #endif
|
---|
| 765 |
|
---|
[1] | 766 | /* MMU memory access macros */
|
---|
| 767 |
|
---|
[2422] | 768 | #if defined(CONFIG_USER_ONLY)
|
---|
[36170] | 769 | #include <assert.h>
|
---|
| 770 | #include "qemu-types.h"
|
---|
| 771 |
|
---|
[2422] | 772 | /* On some host systems the guest address space is reserved on the host.
|
---|
| 773 | * This allows the guest address space to be offset to a convenient location.
|
---|
| 774 | */
|
---|
[37675] | 775 | #if defined(CONFIG_USE_GUEST_BASE)
|
---|
[42601] | 776 | extern uintptr_t guest_base;
|
---|
[37675] | 777 | extern int have_guest_base;
|
---|
[42601] | 778 | extern uintptr_t reserved_va;
|
---|
[37675] | 779 | #define GUEST_BASE guest_base
|
---|
[37689] | 780 | #define RESERVED_VA reserved_va
|
---|
[37675] | 781 | #else
|
---|
| 782 | #define GUEST_BASE 0ul
|
---|
[37689] | 783 | #define RESERVED_VA 0ul
|
---|
[37675] | 784 | #endif
|
---|
[2422] | 785 |
|
---|
| 786 | /* All direct uses of g2h and h2g need to go away for usermode softmmu. */
|
---|
[42601] | 787 | #define g2h(x) ((void *)((uintptr_t)(x) + GUEST_BASE))
|
---|
[37689] | 788 |
|
---|
| 789 | #if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
|
---|
| 790 | #define h2g_valid(x) 1
|
---|
| 791 | #else
|
---|
| 792 | #define h2g_valid(x) ({ \
|
---|
[42601] | 793 | uintptr_t __guest = (uintptr_t)(x) - GUEST_BASE; \
|
---|
[37689] | 794 | __guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS); \
|
---|
| 795 | })
|
---|
| 796 | #endif
|
---|
| 797 |
|
---|
[36170] | 798 | #define h2g(x) ({ \
|
---|
[42601] | 799 | uintptr_t __ret = (uintptr_t)(x) - GUEST_BASE; \
|
---|
[36170] | 800 | /* Check if given address fits target address space */ \
|
---|
[37689] | 801 | assert(h2g_valid(x)); \
|
---|
[36170] | 802 | (abi_ulong)__ret; \
|
---|
| 803 | })
|
---|
[36140] | 804 |
|
---|
[2422] | 805 | #define saddr(x) g2h(x)
|
---|
| 806 | #define laddr(x) g2h(x)
|
---|
| 807 |
|
---|
| 808 | #else /* !CONFIG_USER_ONLY */
|
---|
[1] | 809 | /* NOTE: we use double casts if pointers and target_ulong have
|
---|
| 810 | different sizes */
|
---|
[42601] | 811 | #define saddr(x) (uint8_t *)(intptr_t)(x)
|
---|
| 812 | #define laddr(x) (uint8_t *)(intptr_t)(x)
|
---|
[2422] | 813 | #endif
|
---|
[1] | 814 |
|
---|
[2422] | 815 | #define ldub_raw(p) ldub_p(laddr((p)))
|
---|
| 816 | #define ldsb_raw(p) ldsb_p(laddr((p)))
|
---|
| 817 | #define lduw_raw(p) lduw_p(laddr((p)))
|
---|
| 818 | #define ldsw_raw(p) ldsw_p(laddr((p)))
|
---|
| 819 | #define ldl_raw(p) ldl_p(laddr((p)))
|
---|
| 820 | #define ldq_raw(p) ldq_p(laddr((p)))
|
---|
| 821 | #define ldfl_raw(p) ldfl_p(laddr((p)))
|
---|
| 822 | #define ldfq_raw(p) ldfq_p(laddr((p)))
|
---|
| 823 | #define stb_raw(p, v) stb_p(saddr((p)), v)
|
---|
| 824 | #define stw_raw(p, v) stw_p(saddr((p)), v)
|
---|
| 825 | #define stl_raw(p, v) stl_p(saddr((p)), v)
|
---|
| 826 | #define stq_raw(p, v) stq_p(saddr((p)), v)
|
---|
| 827 | #define stfl_raw(p, v) stfl_p(saddr((p)), v)
|
---|
| 828 | #define stfq_raw(p, v) stfq_p(saddr((p)), v)
|
---|
[1] | 829 |
|
---|
[2422] | 830 |
|
---|
[6532] | 831 | #if defined(CONFIG_USER_ONLY)
|
---|
[1] | 832 |
|
---|
| 833 | /* if user mode, no other memory access functions */
|
---|
| 834 | #define ldub(p) ldub_raw(p)
|
---|
| 835 | #define ldsb(p) ldsb_raw(p)
|
---|
| 836 | #define lduw(p) lduw_raw(p)
|
---|
| 837 | #define ldsw(p) ldsw_raw(p)
|
---|
| 838 | #define ldl(p) ldl_raw(p)
|
---|
| 839 | #define ldq(p) ldq_raw(p)
|
---|
| 840 | #define ldfl(p) ldfl_raw(p)
|
---|
| 841 | #define ldfq(p) ldfq_raw(p)
|
---|
| 842 | #define stb(p, v) stb_raw(p, v)
|
---|
| 843 | #define stw(p, v) stw_raw(p, v)
|
---|
| 844 | #define stl(p, v) stl_raw(p, v)
|
---|
| 845 | #define stq(p, v) stq_raw(p, v)
|
---|
| 846 | #define stfl(p, v) stfl_raw(p, v)
|
---|
| 847 | #define stfq(p, v) stfq_raw(p, v)
|
---|
| 848 |
|
---|
| 849 | #define ldub_code(p) ldub_raw(p)
|
---|
| 850 | #define ldsb_code(p) ldsb_raw(p)
|
---|
| 851 | #define lduw_code(p) lduw_raw(p)
|
---|
| 852 | #define ldsw_code(p) ldsw_raw(p)
|
---|
| 853 | #define ldl_code(p) ldl_raw(p)
|
---|
[36140] | 854 | #define ldq_code(p) ldq_raw(p)
|
---|
[1] | 855 |
|
---|
| 856 | #define ldub_kernel(p) ldub_raw(p)
|
---|
| 857 | #define ldsb_kernel(p) ldsb_raw(p)
|
---|
| 858 | #define lduw_kernel(p) lduw_raw(p)
|
---|
| 859 | #define ldsw_kernel(p) ldsw_raw(p)
|
---|
| 860 | #define ldl_kernel(p) ldl_raw(p)
|
---|
[36140] | 861 | #define ldq_kernel(p) ldq_raw(p)
|
---|
[1] | 862 | #define ldfl_kernel(p) ldfl_raw(p)
|
---|
| 863 | #define ldfq_kernel(p) ldfq_raw(p)
|
---|
| 864 | #define stb_kernel(p, v) stb_raw(p, v)
|
---|
| 865 | #define stw_kernel(p, v) stw_raw(p, v)
|
---|
| 866 | #define stl_kernel(p, v) stl_raw(p, v)
|
---|
| 867 | #define stq_kernel(p, v) stq_raw(p, v)
|
---|
| 868 | #define stfl_kernel(p, v) stfl_raw(p, v)
|
---|
| 869 | #define stfq_kernel(p, vt) stfq_raw(p, v)
|
---|
| 870 |
|
---|
| 871 | #endif /* defined(CONFIG_USER_ONLY) */
|
---|
| 872 |
|
---|
| 873 | /* page related stuff */
|
---|
| 874 |
|
---|
| 875 | #define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
|
---|
| 876 | #define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
|
---|
| 877 | #define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
|
---|
| 878 |
|
---|
[42601] | 879 | /* ??? These should be the larger of uintptr_t and target_ulong. */
|
---|
| 880 | extern size_t qemu_real_host_page_size;
|
---|
| 881 | extern size_t qemu_host_page_bits;
|
---|
| 882 | extern size_t qemu_host_page_size;
|
---|
| 883 | extern uintptr_t qemu_host_page_mask;
|
---|
[1] | 884 |
|
---|
| 885 | #define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask)
|
---|
| 886 |
|
---|
| 887 | /* same as PROT_xxx */
|
---|
| 888 | #define PAGE_READ 0x0001
|
---|
| 889 | #define PAGE_WRITE 0x0002
|
---|
| 890 | #define PAGE_EXEC 0x0004
|
---|
| 891 | #define PAGE_BITS (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
|
---|
| 892 | #define PAGE_VALID 0x0008
|
---|
| 893 | /* original state of the write flag (used when tracking self-modifying
|
---|
| 894 | code */
|
---|
[6532] | 895 | #define PAGE_WRITE_ORG 0x0010
|
---|
[37689] | 896 | #if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY)
|
---|
| 897 | /* FIXME: Code that sets/uses this is broken and needs to go away. */
|
---|
[13230] | 898 | #define PAGE_RESERVED 0x0020
|
---|
[37689] | 899 | #endif
|
---|
[1] | 900 |
|
---|
[37689] | 901 | #if defined(CONFIG_USER_ONLY)
|
---|
[1] | 902 | void page_dump(FILE *f);
|
---|
[37689] | 903 |
|
---|
| 904 | typedef int (*walk_memory_regions_fn)(void *, abi_ulong,
|
---|
[42601] | 905 | abi_ulong, uintptr_t);
|
---|
[37689] | 906 | int walk_memory_regions(void *, walk_memory_regions_fn);
|
---|
| 907 |
|
---|
[2422] | 908 | int page_get_flags(target_ulong address);
|
---|
| 909 | void page_set_flags(target_ulong start, target_ulong end, int flags);
|
---|
[13230] | 910 | int page_check_range(target_ulong start, target_ulong len, int flags);
|
---|
[37689] | 911 | #endif
|
---|
[1] | 912 |
|
---|
[36170] | 913 | CPUState *cpu_copy(CPUState *env);
|
---|
[36175] | 914 | CPUState *qemu_get_cpu(int cpu);
|
---|
[36170] | 915 |
|
---|
[6532] | 916 | void cpu_dump_state(CPUState *env, FILE *f,
|
---|
[1] | 917 | int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
|
---|
| 918 | int flags);
|
---|
[36140] | 919 | void cpu_dump_statistics (CPUState *env, FILE *f,
|
---|
| 920 | int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
|
---|
| 921 | int flags);
|
---|
[1] | 922 |
|
---|
[36170] | 923 | void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...)
|
---|
[36143] | 924 | #ifndef VBOX
|
---|
[36170] | 925 | __attribute__ ((__format__ (__printf__, 2, 3)));
|
---|
[37689] | 926 | #else /* VBOX */
|
---|
[36170] | 927 | ;
|
---|
[37689] | 928 | #endif /* VBOX */
|
---|
[2422] | 929 | extern CPUState *first_cpu;
|
---|
[1] | 930 | extern CPUState *cpu_single_env;
|
---|
| 931 |
|
---|
| 932 | #define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
|
---|
| 933 | #define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
|
---|
| 934 | #define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
|
---|
[2422] | 935 | #define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */
|
---|
| 936 | #define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */
|
---|
| 937 | #define CPU_INTERRUPT_SMI 0x40 /* (x86 only) SMI interrupt pending */
|
---|
[36140] | 938 | #define CPU_INTERRUPT_DEBUG 0x80 /* Debug event occured. */
|
---|
[13230] | 939 | #define CPU_INTERRUPT_VIRQ 0x100 /* virtual interrupt pending. */
|
---|
| 940 | #define CPU_INTERRUPT_NMI 0x200 /* NMI pending. */
|
---|
[36175] | 941 | #define CPU_INTERRUPT_INIT 0x400 /* INIT pending. */
|
---|
| 942 | #define CPU_INTERRUPT_SIPI 0x800 /* SIPI pending. */
|
---|
| 943 | #define CPU_INTERRUPT_MCE 0x1000 /* (x86 only) MCE pending. */
|
---|
[2422] | 944 |
|
---|
[1] | 945 | #ifdef VBOX
|
---|
| 946 | /** Executes a single instruction. cpu_exec() will normally return EXCP_SINGLE_INSTR. */
|
---|
[37702] | 947 | # define CPU_INTERRUPT_SINGLE_INSTR 0x01000000
|
---|
[1] | 948 | /** Executing a CPU_INTERRUPT_SINGLE_INSTR request, quit the cpu_loop. (for exceptions and suchlike) */
|
---|
[37702] | 949 | # define CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT 0x02000000
|
---|
[1] | 950 | /** VM execution was interrupted by VMR3Reset, VMR3Suspend or VMR3PowerOff. */
|
---|
[37702] | 951 | # define CPU_INTERRUPT_RC 0x04000000
|
---|
[36175] | 952 | /** Exit current TB to process an external request. */
|
---|
[37702] | 953 | # define CPU_INTERRUPT_EXTERNAL_FLUSH_TLB 0x08000000
|
---|
| 954 | /** Exit current TB to process an external request. */
|
---|
[36175] | 955 | # define CPU_INTERRUPT_EXTERNAL_EXIT 0x10000000
|
---|
| 956 | /** Exit current TB to process an external interrupt request. */
|
---|
| 957 | # define CPU_INTERRUPT_EXTERNAL_HARD 0x20000000
|
---|
| 958 | /** Exit current TB to process an external timer request. */
|
---|
| 959 | # define CPU_INTERRUPT_EXTERNAL_TIMER 0x40000000
|
---|
| 960 | /** Exit current TB to process an external DMA request. */
|
---|
| 961 | # define CPU_INTERRUPT_EXTERNAL_DMA 0x80000000
|
---|
[1] | 962 | #endif /* VBOX */
|
---|
| 963 | void cpu_interrupt(CPUState *s, int mask);
|
---|
| 964 | void cpu_reset_interrupt(CPUState *env, int mask);
|
---|
| 965 |
|
---|
[36175] | 966 | void cpu_exit(CPUState *s);
|
---|
| 967 |
|
---|
| 968 | int qemu_cpu_has_work(CPUState *env);
|
---|
| 969 |
|
---|
[36170] | 970 | /* Breakpoint/watchpoint flags */
|
---|
| 971 | #define BP_MEM_READ 0x01
|
---|
| 972 | #define BP_MEM_WRITE 0x02
|
---|
| 973 | #define BP_MEM_ACCESS (BP_MEM_READ | BP_MEM_WRITE)
|
---|
| 974 | #define BP_STOP_BEFORE_ACCESS 0x04
|
---|
| 975 | #define BP_WATCHPOINT_HIT 0x08
|
---|
| 976 | #define BP_GDB 0x10
|
---|
| 977 | #define BP_CPU 0x20
|
---|
[13230] | 978 |
|
---|
[36170] | 979 | int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
|
---|
| 980 | CPUBreakpoint **breakpoint);
|
---|
| 981 | int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags);
|
---|
| 982 | void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint);
|
---|
| 983 | void cpu_breakpoint_remove_all(CPUState *env, int mask);
|
---|
| 984 | int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
|
---|
| 985 | int flags, CPUWatchpoint **watchpoint);
|
---|
| 986 | int cpu_watchpoint_remove(CPUState *env, target_ulong addr,
|
---|
| 987 | target_ulong len, int flags);
|
---|
| 988 | void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint);
|
---|
| 989 | void cpu_watchpoint_remove_all(CPUState *env, int mask);
|
---|
| 990 |
|
---|
[13230] | 991 | #define SSTEP_ENABLE 0x1 /* Enable simulated HW single stepping */
|
---|
| 992 | #define SSTEP_NOIRQ 0x2 /* Do not use IRQ while single stepping */
|
---|
| 993 | #define SSTEP_NOTIMER 0x4 /* Do not Timers while single stepping */
|
---|
| 994 |
|
---|
[1] | 995 | void cpu_single_step(CPUState *env, int enabled);
|
---|
| 996 | void cpu_reset(CPUState *s);
|
---|
[37689] | 997 | int cpu_is_stopped(CPUState *env);
|
---|
| 998 | void run_on_cpu(CPUState *env, void (*func)(void *data), void *data);
|
---|
[1] | 999 |
|
---|
[6532] | 1000 | #define CPU_LOG_TB_OUT_ASM (1 << 0)
|
---|
[1] | 1001 | #define CPU_LOG_TB_IN_ASM (1 << 1)
|
---|
| 1002 | #define CPU_LOG_TB_OP (1 << 2)
|
---|
| 1003 | #define CPU_LOG_TB_OP_OPT (1 << 3)
|
---|
| 1004 | #define CPU_LOG_INT (1 << 4)
|
---|
| 1005 | #define CPU_LOG_EXEC (1 << 5)
|
---|
| 1006 | #define CPU_LOG_PCALL (1 << 6)
|
---|
| 1007 | #define CPU_LOG_IOPORT (1 << 7)
|
---|
| 1008 | #define CPU_LOG_TB_CPU (1 << 8)
|
---|
[36170] | 1009 | #define CPU_LOG_RESET (1 << 9)
|
---|
[1] | 1010 |
|
---|
| 1011 | /* define log items */
|
---|
| 1012 | typedef struct CPULogItem {
|
---|
| 1013 | int mask;
|
---|
| 1014 | const char *name;
|
---|
| 1015 | const char *help;
|
---|
| 1016 | } CPULogItem;
|
---|
| 1017 |
|
---|
[36140] | 1018 | extern const CPULogItem cpu_log_items[];
|
---|
[1] | 1019 |
|
---|
| 1020 | void cpu_set_log(int log_flags);
|
---|
| 1021 | void cpu_set_log_filename(const char *filename);
|
---|
| 1022 | int cpu_str_to_log_mask(const char *str);
|
---|
| 1023 |
|
---|
[37689] | 1024 | #if !defined(CONFIG_USER_ONLY)
|
---|
[1] | 1025 |
|
---|
[37689] | 1026 | /* Return the physical page corresponding to a virtual one. Use it
|
---|
| 1027 | only for debugging because no protection checks are done. Return -1
|
---|
| 1028 | if no page found. */
|
---|
| 1029 | target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
|
---|
| 1030 |
|
---|
[1] | 1031 | /* memory API */
|
---|
[2422] | 1032 |
|
---|
[55] | 1033 | #ifndef VBOX
|
---|
[1] | 1034 | extern int phys_ram_fd;
|
---|
[36140] | 1035 | extern ram_addr_t ram_size;
|
---|
[37689] | 1036 | #endif /* !VBOX */
|
---|
| 1037 |
|
---|
| 1038 | typedef struct RAMBlock {
|
---|
| 1039 | uint8_t *host;
|
---|
| 1040 | ram_addr_t offset;
|
---|
| 1041 | ram_addr_t length;
|
---|
| 1042 | char idstr[256];
|
---|
| 1043 | QLIST_ENTRY(RAMBlock) next;
|
---|
| 1044 | #if defined(__linux__) && !defined(TARGET_S390X)
|
---|
| 1045 | int fd;
|
---|
| 1046 | #endif
|
---|
| 1047 | } RAMBlock;
|
---|
| 1048 |
|
---|
| 1049 | typedef struct RAMList {
|
---|
| 1050 | uint8_t *phys_dirty;
|
---|
| 1051 | #ifdef VBOX
|
---|
| 1052 | /** This is required for bounds checking the phys_ram_dirty accesses.
|
---|
| 1053 | * We have memory ranges (the high PC-BIOS mapping) which causes some pages
|
---|
| 1054 | * to fall outside the dirty map. */
|
---|
| 1055 | RTGCPHYS phys_dirty_size;
|
---|
[37693] | 1056 | #if 1
|
---|
[37689] | 1057 | # define VBOX_RAMLIST_DIRTY_BOUNDS_CHECK_RET(addr,rv) \
|
---|
| 1058 | do { \
|
---|
| 1059 | if (RT_UNLIKELY( ((addr) >> TARGET_PAGE_BITS) >= ram_list.phys_dirty_size)) { \
|
---|
| 1060 | Log(("%s: %RGp\n", __FUNCTION__, (RTGCPHYS)addr)); \
|
---|
| 1061 | return (rv); \
|
---|
| 1062 | } \
|
---|
| 1063 | } while (0)
|
---|
| 1064 | # define VBOX_RAMLIST_DIRTY_BOUNDS_CHECK_RETV(addr) \
|
---|
| 1065 | do { \
|
---|
| 1066 | if (RT_UNLIKELY( ((addr) >> TARGET_PAGE_BITS) >= ram_list.phys_dirty_size)) { \
|
---|
| 1067 | Log(("%s: %RGp\n", __FUNCTION__, (RTGCPHYS)addr)); \
|
---|
| 1068 | return; \
|
---|
| 1069 | } \
|
---|
| 1070 | } while (0)
|
---|
| 1071 | #else
|
---|
| 1072 | # define VBOX_RAMLIST_DIRTY_BOUNDS_CHECK_RET(addr,rv) \
|
---|
| 1073 | AssertMsgReturn(((addr) >> TARGET_PAGE_BITS) < ram_list.phys_dirty_size, ("%#RGp\n", (RTGCPHYS)(addr)), (rv));
|
---|
| 1074 | # define VBOX_RAMLIST_DIRTY_BOUNDS_CHECK_RETV(addr) \
|
---|
| 1075 | AssertMsgReturnVoid(((addr) >> TARGET_PAGE_BITS) < ram_list.phys_dirty_size, ("%#RGp\n", (RTGCPHYS)(addr)));
|
---|
| 1076 | # endif
|
---|
| 1077 | #else
|
---|
| 1078 | # define VBOX_RAMLIST_DIRTY_BOUNDS_CHECK_RET(addr,rv) do {} while()
|
---|
| 1079 | # define VBOX_RAMLIST_DIRTY_BOUNDS_CHECK_RETV(addr) do {} while()
|
---|
[2422] | 1080 | #endif /* VBOX */
|
---|
[37689] | 1081 | QLIST_HEAD(ram, RAMBlock) blocks;
|
---|
| 1082 | } RAMList;
|
---|
| 1083 | extern RAMList ram_list;
|
---|
[1] | 1084 |
|
---|
[37689] | 1085 | extern const char *mem_path;
|
---|
| 1086 | extern int mem_prealloc;
|
---|
| 1087 |
|
---|
[1] | 1088 | /* physical memory access */
|
---|
[13559] | 1089 |
|
---|
| 1090 | /* MMIO pages are identified by a combination of an IO device index and
|
---|
[13839] | 1091 | 3 flags. The ROMD code stores the page ram offset in iotlb entry,
|
---|
[36125] | 1092 | so only a limited number of ids are avaiable. */
|
---|
[13559] | 1093 |
|
---|
[2422] | 1094 | #define IO_MEM_NB_ENTRIES (1 << (TARGET_PAGE_BITS - IO_MEM_SHIFT))
|
---|
[1] | 1095 |
|
---|
[13230] | 1096 | /* Flags stored in the low bits of the TLB virtual address. These are
|
---|
| 1097 | defined so that fast path ram access is all zeros. */
|
---|
| 1098 | /* Zero if TLB entry is valid. */
|
---|
| 1099 | #define TLB_INVALID_MASK (1 << 3)
|
---|
| 1100 | /* Set if TLB entry references a clean RAM page. The iotlb entry will
|
---|
| 1101 | contain the page physical address. */
|
---|
| 1102 | #define TLB_NOTDIRTY (1 << 4)
|
---|
| 1103 | /* Set if TLB entry is an IO callback. */
|
---|
| 1104 | #define TLB_MMIO (1 << 5)
|
---|
| 1105 |
|
---|
[36140] | 1106 | #define VGA_DIRTY_FLAG 0x01
|
---|
| 1107 | #define CODE_DIRTY_FLAG 0x02
|
---|
[13230] | 1108 | #define MIGRATION_DIRTY_FLAG 0x08
|
---|
[2422] | 1109 |
|
---|
[1] | 1110 | /* read dirty bit (return 0 or 1) */
|
---|
[2422] | 1111 | static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
|
---|
[1] | 1112 | {
|
---|
[37689] | 1113 | VBOX_RAMLIST_DIRTY_BOUNDS_CHECK_RET(addr, 0);
|
---|
| 1114 | return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
|
---|
[1] | 1115 | }
|
---|
| 1116 |
|
---|
[37689] | 1117 | static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
|
---|
| 1118 | {
|
---|
| 1119 | VBOX_RAMLIST_DIRTY_BOUNDS_CHECK_RET(addr, 0xff);
|
---|
| 1120 | return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS];
|
---|
| 1121 | }
|
---|
| 1122 |
|
---|
[6532] | 1123 | static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
|
---|
[2422] | 1124 | int dirty_flags)
|
---|
[1] | 1125 | {
|
---|
[37689] | 1126 | VBOX_RAMLIST_DIRTY_BOUNDS_CHECK_RET(addr, 0xff & dirty_flags);
|
---|
| 1127 | return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
|
---|
[1] | 1128 | }
|
---|
| 1129 |
|
---|
[2422] | 1130 | static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
|
---|
| 1131 | {
|
---|
[37689] | 1132 | VBOX_RAMLIST_DIRTY_BOUNDS_CHECK_RETV(addr);
|
---|
| 1133 | ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
|
---|
| 1134 | }
|
---|
| 1135 |
|
---|
| 1136 | static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
|
---|
| 1137 | int dirty_flags)
|
---|
| 1138 | {
|
---|
| 1139 | VBOX_RAMLIST_DIRTY_BOUNDS_CHECK_RET(addr, 0xff);
|
---|
| 1140 | return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
|
---|
| 1141 | }
|
---|
| 1142 |
|
---|
| 1143 | static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
|
---|
| 1144 | int length,
|
---|
| 1145 | int dirty_flags)
|
---|
| 1146 | {
|
---|
| 1147 | int i, mask, len;
|
---|
| 1148 | uint8_t *p;
|
---|
| 1149 |
|
---|
| 1150 | VBOX_RAMLIST_DIRTY_BOUNDS_CHECK_RETV(start);
|
---|
| 1151 | len = length >> TARGET_PAGE_BITS;
|
---|
| 1152 | mask = ~dirty_flags;
|
---|
| 1153 | p = ram_list.phys_dirty + (start >> TARGET_PAGE_BITS);
|
---|
| 1154 | for (i = 0; i < len; i++) {
|
---|
| 1155 | p[i] &= mask;
|
---|
[2422] | 1156 | }
|
---|
| 1157 | }
|
---|
[1] | 1158 |
|
---|
[2422] | 1159 | void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
|
---|
| 1160 | int dirty_flags);
|
---|
| 1161 | void cpu_tlb_update_dirty(CPUState *env);
|
---|
| 1162 |
|
---|
[13230] | 1163 | int cpu_physical_memory_set_dirty_tracking(int enable);
|
---|
| 1164 |
|
---|
| 1165 | int cpu_physical_memory_get_dirty_tracking(void);
|
---|
| 1166 |
|
---|
[36175] | 1167 | int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
|
---|
| 1168 | target_phys_addr_t end_addr);
|
---|
[36170] | 1169 |
|
---|
[1] | 1170 | void dump_exec_info(FILE *f,
|
---|
| 1171 | int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
|
---|
[37689] | 1172 | #endif /* !CONFIG_USER_ONLY */
|
---|
[1] | 1173 |
|
---|
[37689] | 1174 | int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
|
---|
| 1175 | uint8_t *buf, int len, int is_write);
|
---|
[36170] | 1176 |
|
---|
[36175] | 1177 | void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
|
---|
| 1178 | uint64_t mcg_status, uint64_t addr, uint64_t misc);
|
---|
| 1179 |
|
---|
[1] | 1180 | #ifdef VBOX
|
---|
| 1181 | void tb_invalidate_virt(CPUState *env, uint32_t eip);
|
---|
[2422] | 1182 | #endif /* VBOX */
|
---|
[1] | 1183 |
|
---|
| 1184 | #endif /* CPU_ALL_H */
|
---|