Revision fcc803d1

b/target-xtensa/cpu.c
48 48
            XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
49 49
    env->sregs[VECBASE] = env->config->vecbase;
50 50
    env->sregs[IBREAKENABLE] = 0;
51
    env->sregs[ATOMCTL] = xtensa_option_enabled(env->config,
52
            XTENSA_OPTION_ATOMCTL) ? 0x28 : 0x15;
51 53

  
52 54
    env->pending_irq_level = 0;
53 55
    reset_mmu(env);
b/target-xtensa/cpu.h
65 65
    XTENSA_OPTION_FP_COPROCESSOR,
66 66
    XTENSA_OPTION_MP_SYNCHRO,
67 67
    XTENSA_OPTION_CONDITIONAL_STORE,
68
    XTENSA_OPTION_ATOMCTL,
68 69

  
69 70
    /* Interrupts and exceptions */
70 71
    XTENSA_OPTION_EXCEPTION,
......
128 129
    ITLBCFG = 91,
129 130
    DTLBCFG = 92,
130 131
    IBREAKENABLE = 96,
132
    ATOMCTL = 99,
131 133
    IBREAKA = 128,
132 134
    DBREAKA = 144,
133 135
    DBREAKC = 160,
......
193 195

  
194 196
#define REGION_PAGE_MASK 0xe0000000
195 197

  
198
#define PAGE_CACHE_MASK    0x700
199
#define PAGE_CACHE_SHIFT   8
200
#define PAGE_CACHE_INVALID 0x000
201
#define PAGE_CACHE_BYPASS  0x100
202
#define PAGE_CACHE_WT      0x200
203
#define PAGE_CACHE_WB      0x400
204
#define PAGE_CACHE_ISOLATE 0x600
205

  
196 206
enum {
197 207
    /* Static vectors */
198 208
    EXC_RESET,
b/target-xtensa/helper.c
390 390
static unsigned mmu_attr_to_access(uint32_t attr)
391 391
{
392 392
    unsigned access = 0;
393

  
393 394
    if (attr < 12) {
394 395
        access |= PAGE_READ;
395 396
        if (attr & 0x1) {
......
398 399
        if (attr & 0x2) {
399 400
            access |= PAGE_WRITE;
400 401
        }
402

  
403
        switch (attr & 0xc) {
404
        case 0:
405
            access |= PAGE_CACHE_BYPASS;
406
            break;
407

  
408
        case 4:
409
            access |= PAGE_CACHE_WB;
410
            break;
411

  
412
        case 8:
413
            access |= PAGE_CACHE_WT;
414
            break;
415
        }
401 416
    } else if (attr == 13) {
402
        access |= PAGE_READ | PAGE_WRITE;
417
        access |= PAGE_READ | PAGE_WRITE | PAGE_CACHE_ISOLATE;
403 418
    }
404 419
    return access;
405 420
}
......
410 425
 */
411 426
static unsigned region_attr_to_access(uint32_t attr)
412 427
{
413
    unsigned access = 0;
414
    if ((attr < 6 && attr != 3) || attr == 14) {
415
        access |= PAGE_READ | PAGE_WRITE;
416
    }
417
    if (attr > 0 && attr < 6) {
418
        access |= PAGE_EXEC;
419
    }
420
    return access;
428
    static const unsigned access[16] = {
429
         [0] = PAGE_READ | PAGE_WRITE             | PAGE_CACHE_WT,
430
         [1] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WT,
431
         [2] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_BYPASS,
432
         [3] =                          PAGE_EXEC | PAGE_CACHE_WB,
433
         [4] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WB,
434
         [5] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WB,
435
        [14] = PAGE_READ | PAGE_WRITE             | PAGE_CACHE_ISOLATE,
436
    };
437

  
438
    return access[attr & 0xf];
421 439
}
422 440

  
423 441
static bool is_access_granted(unsigned access, int is_write)
......
566 584
    } else {
567 585
        *paddr = vaddr;
568 586
        *page_size = TARGET_PAGE_SIZE;
569
        *access = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
587
        *access = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_BYPASS;
570 588
        return 0;
571 589
    }
572 590
}
......
599 617
                xtensa_tlb_get_entry(env, dtlb, wi, ei);
600 618

  
601 619
            if (entry->asid) {
620
                static const char * const cache_text[8] = {
621
                    [PAGE_CACHE_BYPASS >> PAGE_CACHE_SHIFT] = "Bypass",
622
                    [PAGE_CACHE_WT >> PAGE_CACHE_SHIFT] = "WT",
623
                    [PAGE_CACHE_WB >> PAGE_CACHE_SHIFT] = "WB",
624
                    [PAGE_CACHE_ISOLATE >> PAGE_CACHE_SHIFT] = "Isolate",
625
                };
602 626
                unsigned access = attr_to_access(entry->attr);
627
                unsigned cache_idx = (access & PAGE_CACHE_MASK) >>
628
                    PAGE_CACHE_SHIFT;
603 629

  
604 630
                if (print_header) {
605 631
                    print_header = false;
606 632
                    cpu_fprintf(f, "Way %u (%d %s)\n", wi, sz, sz_text);
607 633
                    cpu_fprintf(f,
608
                            "\tVaddr       Paddr       ASID  Attr RWX\n"
609
                            "\t----------  ----------  ----  ---- ---\n");
634
                            "\tVaddr       Paddr       ASID  Attr RWX Cache\n"
635
                            "\t----------  ----------  ----  ---- --- -------\n");
610 636
                }
611 637
                cpu_fprintf(f,
612
                        "\t0x%08x  0x%08x  0x%02x  0x%02x %c%c%c\n",
638
                        "\t0x%08x  0x%08x  0x%02x  0x%02x %c%c%c %-7s\n",
613 639
                        entry->vaddr,
614 640
                        entry->paddr,
615 641
                        entry->asid,
616 642
                        entry->attr,
617 643
                        (access & PAGE_READ) ? 'R' : '-',
618 644
                        (access & PAGE_WRITE) ? 'W' : '-',
619
                        (access & PAGE_EXEC) ? 'X' : '-');
645
                        (access & PAGE_EXEC) ? 'X' : '-',
646
                        cache_text[cache_idx] ? cache_text[cache_idx] :
647
                            "Invalid");
620 648
            }
621 649
        }
622 650
    }
b/target-xtensa/helper.h
23 23
DEF_HELPER_3(timer_irq, void, env, i32, i32)
24 24
DEF_HELPER_2(advance_ccount, void, env, i32)
25 25
DEF_HELPER_1(check_interrupts, void, env)
26
DEF_HELPER_3(check_atomctl, void, env, i32, i32)
26 27

  
27 28
DEF_HELPER_2(wsr_rasid, void, env, i32)
28 29
DEF_HELPER_FLAGS_3(rtlb0, TCG_CALL_NO_RWG_SE, i32, env, i32, i32)
b/target-xtensa/op_helper.c
415 415
    check_interrupts(env);
416 416
}
417 417

  
418
/*!
419
 * Check vaddr accessibility/cache attributes and raise an exception if
420
 * specified by the ATOMCTL SR.
421
 *
422
 * Note: local memory exclusion is not implemented
423
 */
424
void HELPER(check_atomctl)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr)
425
{
426
    uint32_t paddr, page_size, access;
427
    uint32_t atomctl = env->sregs[ATOMCTL];
428
    int rc = xtensa_get_physical_addr(env, true, vaddr, 1,
429
            xtensa_get_cring(env), &paddr, &page_size, &access);
430

  
431
    /*
432
     * s32c1i never causes LOAD_PROHIBITED_CAUSE exceptions,
433
     * see opcode description in the ISA
434
     */
435
    if (rc == 0 &&
436
            (access & (PAGE_READ | PAGE_WRITE)) != (PAGE_READ | PAGE_WRITE)) {
437
        rc = STORE_PROHIBITED_CAUSE;
438
    }
439

  
440
    if (rc) {
441
        HELPER(exception_cause_vaddr)(env, pc, rc, vaddr);
442
    }
443

  
444
    /*
445
     * When data cache is not configured use ATOMCTL bypass field.
446
     * See ISA, 4.3.12.4 The Atomic Operation Control Register (ATOMCTL)
447
     * under the Conditional Store Option.
448
     */
449
    if (!xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) {
450
        access = PAGE_CACHE_BYPASS;
451
    }
452

  
453
    switch (access & PAGE_CACHE_MASK) {
454
    case PAGE_CACHE_WB:
455
        atomctl >>= 2;
456
    case PAGE_CACHE_WT:
457
        atomctl >>= 2;
458
    case PAGE_CACHE_BYPASS:
459
        if ((atomctl & 0x3) == 0) {
460
            HELPER(exception_cause_vaddr)(env, pc,
461
                    LOAD_STORE_ERROR_CAUSE, vaddr);
462
        }
463
        break;
464

  
465
    case PAGE_CACHE_ISOLATE:
466
        HELPER(exception_cause_vaddr)(env, pc,
467
                LOAD_STORE_ERROR_CAUSE, vaddr);
468
        break;
469

  
470
    default:
471
        break;
472
    }
473
}
474

  
418 475
void HELPER(wsr_rasid)(CPUXtensaState *env, uint32_t v)
419 476
{
420 477
    v = (v & 0xffffff00) | 0x1;
b/target-xtensa/overlay_tool.h
42 42
#define XCHAL_VECBASE_RESET_VADDR 0
43 43
#endif
44 44

  
45
#ifndef XCHAL_HW_MIN_VERSION
46
#define XCHAL_HW_MIN_VERSION 0
47
#endif
48

  
45 49
#define XCHAL_OPTION(xchal, qemu) ((xchal) ? XTENSA_OPTION_BIT(qemu) : 0)
46 50

  
47 51
#define XTENSA_OPTIONS ( \
......
62 66
    XCHAL_OPTION(XCHAL_HAVE_FP, XTENSA_OPTION_FP_COPROCESSOR) | \
63 67
    XCHAL_OPTION(XCHAL_HAVE_RELEASE_SYNC, XTENSA_OPTION_MP_SYNCHRO) | \
64 68
    XCHAL_OPTION(XCHAL_HAVE_S32C1I, XTENSA_OPTION_CONDITIONAL_STORE) | \
69
    XCHAL_OPTION(XCHAL_HAVE_S32C1I && XCHAL_HW_MIN_VERSION >= 230000, \
70
        XTENSA_OPTION_ATOMCTL) | \
65 71
    /* Interrupts and exceptions */ \
66 72
    XCHAL_OPTION(XCHAL_HAVE_EXCEPTIONS, XTENSA_OPTION_EXCEPTION) | \
67 73
    XCHAL_OPTION(XCHAL_HAVE_VECBASE, XTENSA_OPTION_RELOCATABLE_VECTOR) | \
b/target-xtensa/translate.c
99 99
    [ITLBCFG] = "ITLBCFG",
100 100
    [DTLBCFG] = "DTLBCFG",
101 101
    [IBREAKENABLE] = "IBREAKENABLE",
102
    [ATOMCTL] = "ATOMCTL",
102 103
    [IBREAKA] = "IBREAKA0",
103 104
    [IBREAKA + 1] = "IBREAKA1",
104 105
    [DBREAKA] = "DBREAKA0",
......
556 557
    gen_jumpi_check_loop_end(dc, 0);
557 558
}
558 559

  
560
static void gen_wsr_atomctl(DisasContext *dc, uint32_t sr, TCGv_i32 v)
561
{
562
    tcg_gen_andi_i32(cpu_SR[sr], v, 0x3f);
563
}
564

  
559 565
static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
560 566
{
561 567
    unsigned id = sr - IBREAKA;
......
693 699
        [ITLBCFG] = gen_wsr_tlbcfg,
694 700
        [DTLBCFG] = gen_wsr_tlbcfg,
695 701
        [IBREAKENABLE] = gen_wsr_ibreakenable,
702
        [ATOMCTL] = gen_wsr_atomctl,
696 703
        [IBREAKA] = gen_wsr_ibreaka,
697 704
        [IBREAKA + 1] = gen_wsr_ibreaka,
698 705
        [DBREAKA] = gen_wsr_dbreaka,
......
2317 2324
                int label = gen_new_label();
2318 2325
                TCGv_i32 tmp = tcg_temp_local_new_i32();
2319 2326
                TCGv_i32 addr = tcg_temp_local_new_i32();
2327
                TCGv_i32 tpc;
2320 2328

  
2321 2329
                tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);
2322 2330
                tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
2323 2331
                gen_load_store_alignment(dc, 2, addr, true);
2332

  
2333
                gen_advance_ccount(dc);
2334
                tpc = tcg_const_i32(dc->pc);
2335
                gen_helper_check_atomctl(cpu_env, tpc, addr);
2324 2336
                tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring);
2325 2337
                tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],
2326 2338
                        cpu_SR[SCOMPARE1], label);
......
2328 2340
                tcg_gen_qemu_st32(tmp, addr, dc->cring);
2329 2341

  
2330 2342
                gen_set_label(label);
2343
                tcg_temp_free(tpc);
2331 2344
                tcg_temp_free(addr);
2332 2345
                tcg_temp_free(tmp);
2333 2346
            }

Also available in: Unified diff