mips_cmgcr.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
  7. * Authors: Sanjay Lal <sanjayl@kymasys.com>
  8. *
  9. * Copyright (C) 2015 Imagination Technologies
  10. */
  11. #include "qemu/osdep.h"
  12. #include "qemu/log.h"
  13. #include "qemu/module.h"
  14. #include "hw/sysbus.h"
  15. #include "migration/vmstate.h"
  16. #include "hw/misc/mips_cmgcr.h"
  17. #include "hw/misc/mips_cpc.h"
  18. #include "hw/qdev-properties.h"
  19. #include "hw/intc/mips_gic.h"
  20. static inline bool is_cpc_connected(MIPSGCRState *s)
  21. {
  22. return s->cpc_mr != NULL;
  23. }
  24. static inline bool is_gic_connected(MIPSGCRState *s)
  25. {
  26. return s->gic_mr != NULL;
  27. }
  28. static inline void update_gcr_base(MIPSGCRState *gcr, uint64_t val)
  29. {
  30. CPUState *cpu;
  31. MIPSCPU *mips_cpu;
  32. gcr->gcr_base = val & GCR_BASE_GCRBASE_MSK;
  33. memory_region_set_address(&gcr->iomem, gcr->gcr_base);
  34. CPU_FOREACH(cpu) {
  35. mips_cpu = MIPS_CPU(cpu);
  36. mips_cpu->env.CP0_CMGCRBase = gcr->gcr_base >> 4;
  37. }
  38. }
  39. static inline void update_cpc_base(MIPSGCRState *gcr, uint64_t val)
  40. {
  41. if (is_cpc_connected(gcr)) {
  42. gcr->cpc_base = val & GCR_CPC_BASE_MSK;
  43. memory_region_transaction_begin();
  44. memory_region_set_address(gcr->cpc_mr,
  45. gcr->cpc_base & GCR_CPC_BASE_CPCBASE_MSK);
  46. memory_region_set_enabled(gcr->cpc_mr,
  47. gcr->cpc_base & GCR_CPC_BASE_CPCEN_MSK);
  48. memory_region_transaction_commit();
  49. }
  50. }
  51. static inline void update_gic_base(MIPSGCRState *gcr, uint64_t val)
  52. {
  53. if (is_gic_connected(gcr)) {
  54. gcr->gic_base = val & GCR_GIC_BASE_MSK;
  55. memory_region_transaction_begin();
  56. memory_region_set_address(gcr->gic_mr,
  57. gcr->gic_base & GCR_GIC_BASE_GICBASE_MSK);
  58. memory_region_set_enabled(gcr->gic_mr,
  59. gcr->gic_base & GCR_GIC_BASE_GICEN_MSK);
  60. memory_region_transaction_commit();
  61. }
  62. }
  63. /* Read GCR registers */
  64. static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size)
  65. {
  66. MIPSGCRState *gcr = (MIPSGCRState *) opaque;
  67. MIPSGCRVPState *current_vps = &gcr->vps[current_cpu->cpu_index];
  68. MIPSGCRVPState *other_vps = &gcr->vps[current_vps->other];
  69. switch (addr) {
  70. /* Global Control Block Register */
  71. case GCR_CONFIG_OFS:
  72. /* Set PCORES to 0 */
  73. return 0;
  74. case GCR_BASE_OFS:
  75. return gcr->gcr_base;
  76. case GCR_REV_OFS:
  77. return gcr->gcr_rev;
  78. case GCR_GIC_BASE_OFS:
  79. return gcr->gic_base;
  80. case GCR_CPC_BASE_OFS:
  81. return gcr->cpc_base;
  82. case GCR_GIC_STATUS_OFS:
  83. return is_gic_connected(gcr);
  84. case GCR_CPC_STATUS_OFS:
  85. return is_cpc_connected(gcr);
  86. case GCR_L2_CONFIG_OFS:
  87. /* L2 BYPASS */
  88. return GCR_L2_CONFIG_BYPASS_MSK;
  89. /* Core-Local and Core-Other Control Blocks */
  90. case MIPS_CLCB_OFS + GCR_CL_CONFIG_OFS:
  91. case MIPS_COCB_OFS + GCR_CL_CONFIG_OFS:
  92. /* Set PVP to # of VPs - 1 */
  93. return gcr->num_vps - 1;
  94. case MIPS_CLCB_OFS + GCR_CL_RESETBASE_OFS:
  95. return current_vps->reset_base;
  96. case MIPS_COCB_OFS + GCR_CL_RESETBASE_OFS:
  97. return other_vps->reset_base;
  98. case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS:
  99. return current_vps->other;
  100. case MIPS_COCB_OFS + GCR_CL_OTHER_OFS:
  101. return other_vps->other;
  102. default:
  103. qemu_log_mask(LOG_UNIMP, "Read %d bytes at GCR offset 0x%" HWADDR_PRIx
  104. "\n", size, addr);
  105. return 0;
  106. }
  107. return 0;
  108. }
  109. static inline target_ulong get_exception_base(MIPSGCRVPState *vps)
  110. {
  111. /* TODO: BEV_BASE and SELECT_BEV */
  112. return (int32_t)(vps->reset_base & GCR_CL_RESET_BASE_RESETBASE_MSK);
  113. }
  114. /* Write GCR registers */
  115. static void gcr_write(void *opaque, hwaddr addr, uint64_t data, unsigned size)
  116. {
  117. MIPSGCRState *gcr = (MIPSGCRState *)opaque;
  118. MIPSGCRVPState *current_vps = &gcr->vps[current_cpu->cpu_index];
  119. MIPSGCRVPState *other_vps = &gcr->vps[current_vps->other];
  120. switch (addr) {
  121. case GCR_BASE_OFS:
  122. update_gcr_base(gcr, data);
  123. break;
  124. case GCR_GIC_BASE_OFS:
  125. update_gic_base(gcr, data);
  126. break;
  127. case GCR_CPC_BASE_OFS:
  128. update_cpc_base(gcr, data);
  129. break;
  130. case MIPS_CLCB_OFS + GCR_CL_RESETBASE_OFS:
  131. current_vps->reset_base = data & GCR_CL_RESET_BASE_MSK;
  132. cpu_set_exception_base(current_cpu->cpu_index,
  133. get_exception_base(current_vps));
  134. break;
  135. case MIPS_COCB_OFS + GCR_CL_RESETBASE_OFS:
  136. other_vps->reset_base = data & GCR_CL_RESET_BASE_MSK;
  137. cpu_set_exception_base(current_vps->other,
  138. get_exception_base(other_vps));
  139. break;
  140. case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS:
  141. if ((data & GCR_CL_OTHER_MSK) < gcr->num_vps) {
  142. current_vps->other = data & GCR_CL_OTHER_MSK;
  143. }
  144. break;
  145. case MIPS_COCB_OFS + GCR_CL_OTHER_OFS:
  146. if ((data & GCR_CL_OTHER_MSK) < gcr->num_vps) {
  147. other_vps->other = data & GCR_CL_OTHER_MSK;
  148. }
  149. break;
  150. default:
  151. qemu_log_mask(LOG_UNIMP, "Write %d bytes at GCR offset 0x%" HWADDR_PRIx
  152. " 0x%" PRIx64 "\n", size, addr, data);
  153. break;
  154. }
  155. }
  156. static const MemoryRegionOps gcr_ops = {
  157. .read = gcr_read,
  158. .write = gcr_write,
  159. .endianness = DEVICE_NATIVE_ENDIAN,
  160. .impl = {
  161. .max_access_size = 8,
  162. },
  163. };
  164. static void mips_gcr_init(Object *obj)
  165. {
  166. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  167. MIPSGCRState *s = MIPS_GCR(obj);
  168. memory_region_init_io(&s->iomem, OBJECT(s), &gcr_ops, s,
  169. "mips-gcr", GCR_ADDRSPACE_SZ);
  170. sysbus_init_mmio(sbd, &s->iomem);
  171. }
  172. static void mips_gcr_reset(DeviceState *dev)
  173. {
  174. MIPSGCRState *s = MIPS_GCR(dev);
  175. int i;
  176. update_gic_base(s, 0);
  177. update_cpc_base(s, 0);
  178. for (i = 0; i < s->num_vps; i++) {
  179. s->vps[i].other = 0;
  180. s->vps[i].reset_base = 0xBFC00000 & GCR_CL_RESET_BASE_MSK;
  181. cpu_set_exception_base(i, get_exception_base(&s->vps[i]));
  182. }
  183. }
  184. static const VMStateDescription vmstate_mips_gcr = {
  185. .name = "mips-gcr",
  186. .version_id = 0,
  187. .minimum_version_id = 0,
  188. .fields = (VMStateField[]) {
  189. VMSTATE_UINT64(cpc_base, MIPSGCRState),
  190. VMSTATE_END_OF_LIST()
  191. },
  192. };
  193. static Property mips_gcr_properties[] = {
  194. DEFINE_PROP_UINT32("num-vp", MIPSGCRState, num_vps, 1),
  195. DEFINE_PROP_INT32("gcr-rev", MIPSGCRState, gcr_rev, 0x800),
  196. DEFINE_PROP_UINT64("gcr-base", MIPSGCRState, gcr_base, GCR_BASE_ADDR),
  197. DEFINE_PROP_LINK("gic", MIPSGCRState, gic_mr, TYPE_MEMORY_REGION,
  198. MemoryRegion *),
  199. DEFINE_PROP_LINK("cpc", MIPSGCRState, cpc_mr, TYPE_MEMORY_REGION,
  200. MemoryRegion *),
  201. DEFINE_PROP_END_OF_LIST(),
  202. };
  203. static void mips_gcr_realize(DeviceState *dev, Error **errp)
  204. {
  205. MIPSGCRState *s = MIPS_GCR(dev);
  206. /* Create local set of registers for each VP */
  207. s->vps = g_new(MIPSGCRVPState, s->num_vps);
  208. }
  209. static void mips_gcr_class_init(ObjectClass *klass, void *data)
  210. {
  211. DeviceClass *dc = DEVICE_CLASS(klass);
  212. device_class_set_props(dc, mips_gcr_properties);
  213. dc->vmsd = &vmstate_mips_gcr;
  214. dc->reset = mips_gcr_reset;
  215. dc->realize = mips_gcr_realize;
  216. }
  217. static const TypeInfo mips_gcr_info = {
  218. .name = TYPE_MIPS_GCR,
  219. .parent = TYPE_SYS_BUS_DEVICE,
  220. .instance_size = sizeof(MIPSGCRState),
  221. .instance_init = mips_gcr_init,
  222. .class_init = mips_gcr_class_init,
  223. };
  224. static void mips_gcr_register_types(void)
  225. {
  226. type_register_static(&mips_gcr_info);
  227. }
  228. type_init(mips_gcr_register_types)