1fcf5ef2aSThomas Huth /* 2fcf5ef2aSThomas Huth * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab. 3fcf5ef2aSThomas Huth * All rights reserved. 4fcf5ef2aSThomas Huth * 5fcf5ef2aSThomas Huth * Redistribution and use in source and binary forms, with or without 6fcf5ef2aSThomas Huth * modification, are permitted provided that the following conditions are met: 7fcf5ef2aSThomas Huth * * Redistributions of source code must retain the above copyright 8fcf5ef2aSThomas Huth * notice, this list of conditions and the following disclaimer. 9fcf5ef2aSThomas Huth * * Redistributions in binary form must reproduce the above copyright 10fcf5ef2aSThomas Huth * notice, this list of conditions and the following disclaimer in the 11fcf5ef2aSThomas Huth * documentation and/or other materials provided with the distribution. 12fcf5ef2aSThomas Huth * * Neither the name of the Open Source and Linux Lab nor the 13fcf5ef2aSThomas Huth * names of its contributors may be used to endorse or promote products 14fcf5ef2aSThomas Huth * derived from this software without specific prior written permission. 15fcf5ef2aSThomas Huth * 16fcf5ef2aSThomas Huth * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17fcf5ef2aSThomas Huth * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18fcf5ef2aSThomas Huth * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19fcf5ef2aSThomas Huth * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20fcf5ef2aSThomas Huth * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21fcf5ef2aSThomas Huth * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22fcf5ef2aSThomas Huth * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23fcf5ef2aSThomas Huth * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24fcf5ef2aSThomas Huth * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25fcf5ef2aSThomas Huth * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26fcf5ef2aSThomas Huth */ 27fcf5ef2aSThomas Huth 28fcf5ef2aSThomas Huth #include "qemu/osdep.h" 2947e20887SAlex Bennée #include "qemu/main-loop.h" 30fcf5ef2aSThomas Huth #include "cpu.h" 31fcf5ef2aSThomas Huth #include "exec/helper-proto.h" 32fcf5ef2aSThomas Huth #include "qemu/host-utils.h" 33fcf5ef2aSThomas Huth #include "exec/exec-all.h" 34fcf5ef2aSThomas Huth #include "exec/cpu_ldst.h" 35fcf5ef2aSThomas Huth #include "exec/address-spaces.h" 36fcf5ef2aSThomas Huth #include "qemu/timer.h" 37fcf5ef2aSThomas Huth 38ba7651fbSMax Filippov #ifndef CONFIG_USER_ONLY 39ba7651fbSMax Filippov 4059a71f75SMax Filippov void HELPER(update_ccount)(CPUXtensaState *env) 41fcf5ef2aSThomas Huth { 4259a71f75SMax Filippov uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 4359a71f75SMax Filippov 4459a71f75SMax Filippov env->ccount_time = now; 4559a71f75SMax Filippov env->sregs[CCOUNT] = env->ccount_base + 4659a71f75SMax Filippov (uint32_t)((now - env->time_base) * 4759a71f75SMax Filippov env->config->clock_freq_khz / 1000000); 48fcf5ef2aSThomas Huth } 49fcf5ef2aSThomas Huth 5059a71f75SMax Filippov void HELPER(wsr_ccount)(CPUXtensaState *env, uint32_t v) 51fcf5ef2aSThomas Huth { 5259a71f75SMax Filippov int i; 5359a71f75SMax Filippov 5459a71f75SMax Filippov HELPER(update_ccount)(env); 5559a71f75SMax Filippov env->ccount_base += v - env->sregs[CCOUNT]; 5659a71f75SMax Filippov for (i = 0; i < env->config->nccompare; ++i) { 5759a71f75SMax Filippov HELPER(update_ccompare)(env, i); 5859a71f75SMax Filippov } 5959a71f75SMax Filippov } 6059a71f75SMax Filippov 6159a71f75SMax Filippov void HELPER(update_ccompare)(CPUXtensaState *env, uint32_t i) 6259a71f75SMax Filippov { 6359a71f75SMax Filippov uint64_t dcc; 6459a71f75SMax Filippov 65*d73415a3SStefan Hajnoczi qatomic_and(&env->sregs[INTSET], 66fa92bd4aSMax Filippov ~(1u << env->config->timerint[i])); 6759a71f75SMax Filippov HELPER(update_ccount)(env); 6859a71f75SMax Filippov dcc = (uint64_t)(env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] - 1) + 1; 6959a71f75SMax Filippov timer_mod(env->ccompare[i].timer, 7059a71f75SMax Filippov env->ccount_time + (dcc * 1000000) / env->config->clock_freq_khz); 71d2132510SMax Filippov env->yield_needed = 1; 72fcf5ef2aSThomas Huth } 73fcf5ef2aSThomas Huth 74fcf5ef2aSThomas Huth /*! 75fcf5ef2aSThomas Huth * Check vaddr accessibility/cache attributes and raise an exception if 76fcf5ef2aSThomas Huth * specified by the ATOMCTL SR. 77fcf5ef2aSThomas Huth * 78fcf5ef2aSThomas Huth * Note: local memory exclusion is not implemented 79fcf5ef2aSThomas Huth */ 80fcf5ef2aSThomas Huth void HELPER(check_atomctl)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr) 81fcf5ef2aSThomas Huth { 82fcf5ef2aSThomas Huth uint32_t paddr, page_size, access; 83fcf5ef2aSThomas Huth uint32_t atomctl = env->sregs[ATOMCTL]; 84fcf5ef2aSThomas Huth int rc = xtensa_get_physical_addr(env, true, vaddr, 1, 85fcf5ef2aSThomas Huth xtensa_get_cring(env), &paddr, &page_size, &access); 86fcf5ef2aSThomas Huth 87fcf5ef2aSThomas Huth /* 88fcf5ef2aSThomas Huth * s32c1i never causes LOAD_PROHIBITED_CAUSE exceptions, 89fcf5ef2aSThomas Huth * see opcode description in the ISA 90fcf5ef2aSThomas Huth */ 91fcf5ef2aSThomas Huth if (rc == 0 && 92fcf5ef2aSThomas Huth (access & (PAGE_READ | PAGE_WRITE)) != (PAGE_READ | PAGE_WRITE)) { 93fcf5ef2aSThomas Huth rc = STORE_PROHIBITED_CAUSE; 94fcf5ef2aSThomas Huth } 95fcf5ef2aSThomas Huth 96fcf5ef2aSThomas Huth if (rc) { 97fcf5ef2aSThomas Huth HELPER(exception_cause_vaddr)(env, pc, rc, vaddr); 98fcf5ef2aSThomas Huth } 99fcf5ef2aSThomas Huth 100fcf5ef2aSThomas Huth /* 101fcf5ef2aSThomas Huth * When data cache is not configured use ATOMCTL bypass field. 102fcf5ef2aSThomas Huth * See ISA, 4.3.12.4 The Atomic Operation Control Register (ATOMCTL) 103fcf5ef2aSThomas Huth * under the Conditional Store Option. 104fcf5ef2aSThomas Huth */ 105fcf5ef2aSThomas Huth if (!xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) { 106fcf5ef2aSThomas Huth access = PAGE_CACHE_BYPASS; 107fcf5ef2aSThomas Huth } 108fcf5ef2aSThomas Huth 109fcf5ef2aSThomas Huth switch (access & PAGE_CACHE_MASK) { 110fcf5ef2aSThomas Huth case PAGE_CACHE_WB: 111fcf5ef2aSThomas Huth atomctl >>= 2; 112fcf5ef2aSThomas Huth /* fall through */ 113fcf5ef2aSThomas Huth case PAGE_CACHE_WT: 114fcf5ef2aSThomas Huth atomctl >>= 2; 115fcf5ef2aSThomas Huth /* fall through */ 116fcf5ef2aSThomas Huth case PAGE_CACHE_BYPASS: 117fcf5ef2aSThomas Huth if ((atomctl & 0x3) == 0) { 118fcf5ef2aSThomas Huth HELPER(exception_cause_vaddr)(env, pc, 119fcf5ef2aSThomas Huth LOAD_STORE_ERROR_CAUSE, vaddr); 120fcf5ef2aSThomas Huth } 121fcf5ef2aSThomas Huth break; 122fcf5ef2aSThomas Huth 123fcf5ef2aSThomas Huth case PAGE_CACHE_ISOLATE: 124fcf5ef2aSThomas Huth HELPER(exception_cause_vaddr)(env, pc, 125fcf5ef2aSThomas Huth LOAD_STORE_ERROR_CAUSE, vaddr); 126fcf5ef2aSThomas Huth break; 127fcf5ef2aSThomas Huth 128fcf5ef2aSThomas Huth default: 129fcf5ef2aSThomas Huth break; 130fcf5ef2aSThomas Huth } 131fcf5ef2aSThomas Huth } 132fcf5ef2aSThomas Huth 133b345e140SMax Filippov void HELPER(check_exclusive)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr, 134b345e140SMax Filippov uint32_t is_write) 135b345e140SMax Filippov { 136b345e140SMax Filippov uint32_t paddr, page_size, access; 137b345e140SMax Filippov uint32_t atomctl = env->sregs[ATOMCTL]; 138b345e140SMax Filippov int rc = xtensa_get_physical_addr(env, true, vaddr, is_write, 139b345e140SMax Filippov xtensa_get_cring(env), &paddr, 140b345e140SMax Filippov &page_size, &access); 141b345e140SMax Filippov 142b345e140SMax Filippov if (rc) { 143b345e140SMax Filippov HELPER(exception_cause_vaddr)(env, pc, rc, vaddr); 144b345e140SMax Filippov } 145b345e140SMax Filippov 146b345e140SMax Filippov /* When data cache is not configured use ATOMCTL bypass field. */ 147b345e140SMax Filippov if (!xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) { 148b345e140SMax Filippov access = PAGE_CACHE_BYPASS; 149b345e140SMax Filippov } 150b345e140SMax Filippov 151b345e140SMax Filippov switch (access & PAGE_CACHE_MASK) { 152b345e140SMax Filippov case PAGE_CACHE_WB: 153b345e140SMax Filippov atomctl >>= 2; 154b345e140SMax Filippov /* fall through */ 155b345e140SMax Filippov case PAGE_CACHE_WT: 156b345e140SMax Filippov atomctl >>= 2; 157b345e140SMax Filippov /* fall through */ 158b345e140SMax Filippov case PAGE_CACHE_BYPASS: 159b345e140SMax Filippov if ((atomctl & 0x3) == 0) { 160b345e140SMax Filippov HELPER(exception_cause_vaddr)(env, pc, 161b345e140SMax Filippov EXCLUSIVE_ERROR_CAUSE, vaddr); 162b345e140SMax Filippov } 163b345e140SMax Filippov break; 164b345e140SMax Filippov 165b345e140SMax Filippov case PAGE_CACHE_ISOLATE: 166b345e140SMax Filippov HELPER(exception_cause_vaddr)(env, pc, 167b345e140SMax Filippov LOAD_STORE_ERROR_CAUSE, vaddr); 168b345e140SMax Filippov break; 169b345e140SMax Filippov 170b345e140SMax Filippov default: 171b345e140SMax Filippov break; 172b345e140SMax Filippov } 173b345e140SMax Filippov } 174b345e140SMax Filippov 1759e03ade4SMax Filippov void HELPER(wsr_memctl)(CPUXtensaState *env, uint32_t v) 1769e03ade4SMax Filippov { 1779e03ade4SMax Filippov if (xtensa_option_enabled(env->config, XTENSA_OPTION_ICACHE)) { 1789e03ade4SMax Filippov if (extract32(v, MEMCTL_IUSEWAYS_SHIFT, MEMCTL_IUSEWAYS_LEN) > 1799e03ade4SMax Filippov env->config->icache_ways) { 1809e03ade4SMax Filippov deposit32(v, MEMCTL_IUSEWAYS_SHIFT, MEMCTL_IUSEWAYS_LEN, 1819e03ade4SMax Filippov env->config->icache_ways); 1829e03ade4SMax Filippov } 1839e03ade4SMax Filippov } 1849e03ade4SMax Filippov if (xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) { 1859e03ade4SMax Filippov if (extract32(v, MEMCTL_DUSEWAYS_SHIFT, MEMCTL_DUSEWAYS_LEN) > 1869e03ade4SMax Filippov env->config->dcache_ways) { 1879e03ade4SMax Filippov deposit32(v, MEMCTL_DUSEWAYS_SHIFT, MEMCTL_DUSEWAYS_LEN, 1889e03ade4SMax Filippov env->config->dcache_ways); 1899e03ade4SMax Filippov } 1909e03ade4SMax Filippov if (extract32(v, MEMCTL_DALLOCWAYS_SHIFT, MEMCTL_DALLOCWAYS_LEN) > 1919e03ade4SMax Filippov env->config->dcache_ways) { 1929e03ade4SMax Filippov deposit32(v, MEMCTL_DALLOCWAYS_SHIFT, MEMCTL_DALLOCWAYS_LEN, 1939e03ade4SMax Filippov env->config->dcache_ways); 1949e03ade4SMax Filippov } 1959e03ade4SMax Filippov } 1969e03ade4SMax Filippov env->sregs[MEMCTL] = v & env->config->memctl_mask; 1979e03ade4SMax Filippov } 1989e03ade4SMax Filippov 199ba7651fbSMax Filippov #endif 200fcf5ef2aSThomas Huth 2013a3c9dc4SMax Filippov uint32_t HELPER(rer)(CPUXtensaState *env, uint32_t addr) 2023a3c9dc4SMax Filippov { 203ba7651fbSMax Filippov #ifndef CONFIG_USER_ONLY 2043a3c9dc4SMax Filippov return address_space_ldl(env->address_space_er, addr, 2052c5b1d2aSAlistair Francis MEMTXATTRS_UNSPECIFIED, NULL); 206ba7651fbSMax Filippov #else 207ba7651fbSMax Filippov return 0; 208ba7651fbSMax Filippov #endif 2093a3c9dc4SMax Filippov } 2103a3c9dc4SMax Filippov 2113a3c9dc4SMax Filippov void HELPER(wer)(CPUXtensaState *env, uint32_t data, uint32_t addr) 2123a3c9dc4SMax Filippov { 213ba7651fbSMax Filippov #ifndef CONFIG_USER_ONLY 2143a3c9dc4SMax Filippov address_space_stl(env->address_space_er, addr, data, 2152c5b1d2aSAlistair Francis MEMTXATTRS_UNSPECIFIED, NULL); 216ba7651fbSMax Filippov #endif 2173a3c9dc4SMax Filippov } 218