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