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,12 +379,55 @@ static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
379 /* 379 /*
380 * UltraSparc IIi I/DMMUs 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 static int get_physical_address_data(CPUState *env, 425 static int get_physical_address_data(CPUState *env,
383 target_phys_addr_t *physical, int *prot, 426 target_phys_addr_t *physical, int *prot,
384 target_ulong address, int rw, int is_user) 427 target_ulong address, int rw, int is_user)
385 { 428 {
386 - target_ulong mask;  
387 unsigned int i; 429 unsigned int i;
  430 + uint64_t context;
388 431
389 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */ 432 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
390 *physical = ultrasparc_truncate_physical(address); 433 *physical = ultrasparc_truncate_physical(address);
@@ -392,26 +435,13 @@ static int get_physical_address_data(CPUState *env, @@ -392,26 +435,13 @@ static int get_physical_address_data(CPUState *env,
392 return 0; 435 return 0;
393 } 436 }
394 437
  438 + context = env->dmmuregs[1] & 0x1fff;
  439 +
395 for (i = 0; i < 64; i++) { 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 // ctx match, vaddr match, valid? 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 // access ok? 445 // access ok?
416 if (((env->dtlb_tte[i] & 0x4) && is_user) || 446 if (((env->dtlb_tte[i] & 0x4) && is_user) ||
417 (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) { 447 (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
@@ -426,8 +456,6 @@ static int get_physical_address_data(CPUState *env, @@ -426,8 +456,6 @@ static int get_physical_address_data(CPUState *env,
426 #endif 456 #endif
427 return 1; 457 return 1;
428 } 458 }
429 - *physical = ((env->dtlb_tte[i] & mask) | (address & ~mask)) &  
430 - 0x1ffffffe000ULL;  
431 *prot = PAGE_READ; 459 *prot = PAGE_READ;
432 if (env->dtlb_tte[i] & 0x2) 460 if (env->dtlb_tte[i] & 0x2)
433 *prot |= PAGE_WRITE; 461 *prot |= PAGE_WRITE;
@@ -437,7 +465,7 @@ static int get_physical_address_data(CPUState *env, @@ -437,7 +465,7 @@ static int get_physical_address_data(CPUState *env,
437 #ifdef DEBUG_MMU 465 #ifdef DEBUG_MMU
438 printf("DMISS at 0x%" PRIx64 "\n", address); 466 printf("DMISS at 0x%" PRIx64 "\n", address);
439 #endif 467 #endif
440 - env->dmmuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff); 468 + env->dmmuregs[6] = (address & ~0x1fffULL) | context;
441 env->exception_index = TT_DMISS; 469 env->exception_index = TT_DMISS;
442 return 1; 470 return 1;
443 } 471 }
@@ -446,8 +474,8 @@ static int get_physical_address_code(CPUState *env, @@ -446,8 +474,8 @@ static int get_physical_address_code(CPUState *env,
446 target_phys_addr_t *physical, int *prot, 474 target_phys_addr_t *physical, int *prot,
447 target_ulong address, int is_user) 475 target_ulong address, int is_user)
448 { 476 {
449 - target_ulong mask;  
450 unsigned int i; 477 unsigned int i;
  478 + uint64_t context;
451 479
452 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) { 480 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
453 /* IMMU disabled */ 481 /* IMMU disabled */
@@ -456,26 +484,13 @@ static int get_physical_address_code(CPUState *env, @@ -456,26 +484,13 @@ static int get_physical_address_code(CPUState *env,
456 return 0; 484 return 0;
457 } 485 }
458 486
  487 + context = env->dmmuregs[1] & 0x1fff;
  488 +
459 for (i = 0; i < 64; i++) { 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 // ctx match, vaddr match, valid? 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 // access ok? 494 // access ok?
480 if ((env->itlb_tte[i] & 0x4) && is_user) { 495 if ((env->itlb_tte[i] & 0x4) && is_user) {
481 if (env->immuregs[3]) /* Fault status register */ 496 if (env->immuregs[3]) /* Fault status register */
@@ -488,8 +503,6 @@ static int get_physical_address_code(CPUState *env, @@ -488,8 +503,6 @@ static int get_physical_address_code(CPUState *env,
488 #endif 503 #endif
489 return 1; 504 return 1;
490 } 505 }
491 - *physical = ((env->itlb_tte[i] & mask) | (address & ~mask)) &  
492 - 0x1ffffffe000ULL;  
493 *prot = PAGE_EXEC; 506 *prot = PAGE_EXEC;
494 return 0; 507 return 0;
495 } 508 }
@@ -498,7 +511,7 @@ static int get_physical_address_code(CPUState *env, @@ -498,7 +511,7 @@ static int get_physical_address_code(CPUState *env,
498 printf("TMISS at 0x%" PRIx64 "\n", address); 511 printf("TMISS at 0x%" PRIx64 "\n", address);
499 #endif 512 #endif
500 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */ 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 env->exception_index = TT_TMISS; 515 env->exception_index = TT_TMISS;
503 return 1; 516 return 1;
504 } 517 }