Commit 536ba0157268494d641d0061bd9fa0c360d1dd78

Authored by Igor Kovalenko
Committed by Blue Swirl
1 parent e8807b14

sparc64: unify mmu tag matching code

This patch extracts common part of sparc64 tag
matching code used by IMMU and DMMU lookups.

Signed-off-by: igor.v.kovalenko@gmail.com

--
Kind regards,
Igor V. Kovalenko
Showing 1 changed file with 57 additions and 44 deletions
target-sparc/helper.c
... ... @@ -379,12 +379,55 @@ static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
379 379 /*
380 380 * UltraSparc IIi I/DMMUs
381 381 */
  382 +
  383 +static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
  384 +{
  385 + return (x & mask) == (y & mask);
  386 +}
  387 +
  388 +// Returns true if TTE tag is valid and matches virtual address value in context
  389 +// requires virtual address mask value calculated from TTE entry size
  390 +static inline int ultrasparc_tag_match(uint64_t tlb_tag, uint64_t tlb_tte,
  391 + uint64_t address, uint64_t context,
  392 + target_phys_addr_t *physical)
  393 +{
  394 + uint64_t mask;
  395 +
  396 + switch ((tlb_tte >> 61) & 3) {
  397 + default:
  398 + case 0x0: // 8k
  399 + mask = 0xffffffffffffe000ULL;
  400 + break;
  401 + case 0x1: // 64k
  402 + mask = 0xffffffffffff0000ULL;
  403 + break;
  404 + case 0x2: // 512k
  405 + mask = 0xfffffffffff80000ULL;
  406 + break;
  407 + case 0x3: // 4M
  408 + mask = 0xffffffffffc00000ULL;
  409 + break;
  410 + }
  411 +
  412 + // valid, context match, virtual address match?
  413 + if ((tlb_tte & 0x8000000000000000ULL) &&
  414 + compare_masked(context, tlb_tag, 0x1fff) &&
  415 + compare_masked(address, tlb_tag, mask))
  416 + {
  417 + // decode physical address
  418 + *physical = ((tlb_tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
  419 + return 1;
  420 + }
  421 +
  422 + return 0;
  423 +}
  424 +
382 425 static int get_physical_address_data(CPUState *env,
383 426 target_phys_addr_t *physical, int *prot,
384 427 target_ulong address, int rw, int is_user)
385 428 {
386   - target_ulong mask;
387 429 unsigned int i;
  430 + uint64_t context;
388 431  
389 432 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
390 433 *physical = ultrasparc_truncate_physical(address);
... ... @@ -392,26 +435,13 @@ static int get_physical_address_data(CPUState *env,
392 435 return 0;
393 436 }
394 437  
  438 + context = env->dmmuregs[1] & 0x1fff;
  439 +
395 440 for (i = 0; i < 64; i++) {
396   - switch ((env->dtlb_tte[i] >> 61) & 3) {
397   - default:
398   - case 0x0: // 8k
399   - mask = 0xffffffffffffe000ULL;
400   - break;
401   - case 0x1: // 64k
402   - mask = 0xffffffffffff0000ULL;
403   - break;
404   - case 0x2: // 512k
405   - mask = 0xfffffffffff80000ULL;
406   - break;
407   - case 0x3: // 4M
408   - mask = 0xffffffffffc00000ULL;
409   - break;
410   - }
411 441 // ctx match, vaddr match, valid?
412   - if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
413   - (address & mask) == (env->dtlb_tag[i] & mask) &&
414   - (env->dtlb_tte[i] & 0x8000000000000000ULL)) {
  442 + if (ultrasparc_tag_match(env->dtlb_tag[i], env->dtlb_tte[i],
  443 + address, context, physical)
  444 + ) {
415 445 // access ok?
416 446 if (((env->dtlb_tte[i] & 0x4) && is_user) ||
417 447 (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
... ... @@ -426,8 +456,6 @@ static int get_physical_address_data(CPUState *env,
426 456 #endif
427 457 return 1;
428 458 }
429   - *physical = ((env->dtlb_tte[i] & mask) | (address & ~mask)) &
430   - 0x1ffffffe000ULL;
431 459 *prot = PAGE_READ;
432 460 if (env->dtlb_tte[i] & 0x2)
433 461 *prot |= PAGE_WRITE;
... ... @@ -437,7 +465,7 @@ static int get_physical_address_data(CPUState *env,
437 465 #ifdef DEBUG_MMU
438 466 printf("DMISS at 0x%" PRIx64 "\n", address);
439 467 #endif
440   - env->dmmuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
  468 + env->dmmuregs[6] = (address & ~0x1fffULL) | context;
441 469 env->exception_index = TT_DMISS;
442 470 return 1;
443 471 }
... ... @@ -446,8 +474,8 @@ static int get_physical_address_code(CPUState *env,
446 474 target_phys_addr_t *physical, int *prot,
447 475 target_ulong address, int is_user)
448 476 {
449   - target_ulong mask;
450 477 unsigned int i;
  478 + uint64_t context;
451 479  
452 480 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
453 481 /* IMMU disabled */
... ... @@ -456,26 +484,13 @@ static int get_physical_address_code(CPUState *env,
456 484 return 0;
457 485 }
458 486  
  487 + context = env->dmmuregs[1] & 0x1fff;
  488 +
459 489 for (i = 0; i < 64; i++) {
460   - switch ((env->itlb_tte[i] >> 61) & 3) {
461   - default:
462   - case 0x0: // 8k
463   - mask = 0xffffffffffffe000ULL;
464   - break;
465   - case 0x1: // 64k
466   - mask = 0xffffffffffff0000ULL;
467   - break;
468   - case 0x2: // 512k
469   - mask = 0xfffffffffff80000ULL;
470   - break;
471   - case 0x3: // 4M
472   - mask = 0xffffffffffc00000ULL;
473   - break;
474   - }
475 490 // ctx match, vaddr match, valid?
476   - if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
477   - (address & mask) == (env->itlb_tag[i] & mask) &&
478   - (env->itlb_tte[i] & 0x8000000000000000ULL)) {
  491 + if (ultrasparc_tag_match(env->itlb_tag[i], env->itlb_tte[i],
  492 + address, context, physical)
  493 + ) {
479 494 // access ok?
480 495 if ((env->itlb_tte[i] & 0x4) && is_user) {
481 496 if (env->immuregs[3]) /* Fault status register */
... ... @@ -488,8 +503,6 @@ static int get_physical_address_code(CPUState *env,
488 503 #endif
489 504 return 1;
490 505 }
491   - *physical = ((env->itlb_tte[i] & mask) | (address & ~mask)) &
492   - 0x1ffffffe000ULL;
493 506 *prot = PAGE_EXEC;
494 507 return 0;
495 508 }
... ... @@ -498,7 +511,7 @@ static int get_physical_address_code(CPUState *env,
498 511 printf("TMISS at 0x%" PRIx64 "\n", address);
499 512 #endif
500 513 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
501   - env->immuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
  514 + env->immuregs[6] = (address & ~0x1fffULL) | context;
502 515 env->exception_index = TT_TMISS;
503 516 return 1;
504 517 }
... ...