mali_mmu.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. * This confidential and proprietary software may be used only as
  3. * authorised by a licensing agreement from ARM Limited
  4. * (C) COPYRIGHT 2007-2013 ARM Limited
  5. * ALL RIGHTS RESERVED
  6. * The entire notice above must be reproduced on all authorised
  7. * copies and copies may only be made to the extent permitted
  8. * by a licensing agreement from ARM Limited.
  9. */
  10. #include "mali_kernel_common.h"
  11. #include "mali_osk.h"
  12. #include "mali_osk_list.h"
  13. #include "mali_ukk.h"
  14. #include "mali_mmu.h"
  15. #include "mali_hw_core.h"
  16. #include "mali_group.h"
  17. #include "mali_mmu_page_directory.h"
  18. /**
  19. * Size of the MMU registers in bytes
  20. */
  21. #define MALI_MMU_REGISTERS_SIZE 0x24
  22. /**
  23. * MMU commands
  24. * These are the commands that can be sent
  25. * to the MMU unit.
  26. */
  27. typedef enum mali_mmu_command {
  28. MALI_MMU_COMMAND_ENABLE_PAGING = 0x00, /**< Enable paging (memory translation) */
  29. MALI_MMU_COMMAND_DISABLE_PAGING = 0x01, /**< Disable paging (memory translation) */
  30. MALI_MMU_COMMAND_ENABLE_STALL = 0x02, /**< Enable stall on page fault */
  31. MALI_MMU_COMMAND_DISABLE_STALL = 0x03, /**< Disable stall on page fault */
  32. MALI_MMU_COMMAND_ZAP_CACHE = 0x04, /**< Zap the entire page table cache */
  33. MALI_MMU_COMMAND_PAGE_FAULT_DONE = 0x05, /**< Page fault processed */
  34. MALI_MMU_COMMAND_HARD_RESET = 0x06 /**< Reset the MMU back to power-on settings */
  35. } mali_mmu_command;
  36. static void mali_mmu_probe_trigger(void *data);
  37. static _mali_osk_errcode_t mali_mmu_probe_ack(void *data);
  38. MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu);
  39. /* page fault queue flush helper pages
  40. * note that the mapping pointers are currently unused outside of the initialization functions */
  41. static u32 mali_page_fault_flush_page_directory = MALI_INVALID_PAGE;
  42. static mali_io_address mali_page_fault_flush_page_directory_mapping = NULL;
  43. static u32 mali_page_fault_flush_page_table = MALI_INVALID_PAGE;
  44. static mali_io_address mali_page_fault_flush_page_table_mapping = NULL;
  45. static u32 mali_page_fault_flush_data_page = MALI_INVALID_PAGE;
  46. static mali_io_address mali_page_fault_flush_data_page_mapping = NULL;
  47. /* an empty page directory (no address valid) which is active on any MMU not currently marked as in use */
  48. static u32 mali_empty_page_directory_phys = MALI_INVALID_PAGE;
  49. static mali_io_address mali_empty_page_directory_virt = NULL;
  50. _mali_osk_errcode_t mali_mmu_initialize(void)
  51. {
  52. /* allocate the helper pages */
  53. mali_empty_page_directory_phys = mali_allocate_empty_page(&mali_empty_page_directory_virt);
  54. if(0 == mali_empty_page_directory_phys) {
  55. MALI_DEBUG_PRINT_ERROR(("Mali MMU: Could not allocate empty page directory.\n"));
  56. mali_empty_page_directory_phys = MALI_INVALID_PAGE;
  57. return _MALI_OSK_ERR_NOMEM;
  58. }
  59. if (_MALI_OSK_ERR_OK != mali_create_fault_flush_pages(&mali_page_fault_flush_page_directory,
  60. &mali_page_fault_flush_page_directory_mapping,
  61. &mali_page_fault_flush_page_table,
  62. &mali_page_fault_flush_page_table_mapping,
  63. &mali_page_fault_flush_data_page,
  64. &mali_page_fault_flush_data_page_mapping)) {
  65. MALI_DEBUG_PRINT_ERROR(("Mali MMU: Could not allocate fault flush pages\n"));
  66. mali_free_empty_page(mali_empty_page_directory_phys, mali_empty_page_directory_virt);
  67. mali_empty_page_directory_phys = MALI_INVALID_PAGE;
  68. mali_empty_page_directory_virt = NULL;
  69. return _MALI_OSK_ERR_NOMEM;
  70. }
  71. return _MALI_OSK_ERR_OK;
  72. }
  73. void mali_mmu_terminate(void)
  74. {
  75. MALI_DEBUG_PRINT(3, ("Mali MMU: terminating\n"));
  76. /* Free global helper pages */
  77. mali_free_empty_page(mali_empty_page_directory_phys, mali_empty_page_directory_virt);
  78. mali_empty_page_directory_phys = MALI_INVALID_PAGE;
  79. mali_empty_page_directory_virt = NULL;
  80. /* Free the page fault flush pages */
  81. mali_destroy_fault_flush_pages(&mali_page_fault_flush_page_directory, &mali_page_fault_flush_page_directory_mapping,
  82. &mali_page_fault_flush_page_table, &mali_page_fault_flush_page_table_mapping,
  83. &mali_page_fault_flush_data_page, &mali_page_fault_flush_data_page_mapping);
  84. }
  85. struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual)
  86. {
  87. struct mali_mmu_core* mmu = NULL;
  88. MALI_DEBUG_ASSERT_POINTER(resource);
  89. MALI_DEBUG_PRINT(2, ("Mali MMU: Creating Mali MMU: %s\n", resource->description));
  90. mmu = _mali_osk_calloc(1,sizeof(struct mali_mmu_core));
  91. if (NULL != mmu) {
  92. if (_MALI_OSK_ERR_OK == mali_hw_core_create(&mmu->hw_core, resource, MALI_MMU_REGISTERS_SIZE)) {
  93. if (_MALI_OSK_ERR_OK == mali_group_add_mmu_core(group, mmu)) {
  94. if (is_virtual) {
  95. /* Skip reset and IRQ setup for virtual MMU */
  96. return mmu;
  97. }
  98. if (_MALI_OSK_ERR_OK == mali_mmu_reset(mmu)) {
  99. /* Setup IRQ handlers (which will do IRQ probing if needed) */
  100. mmu->irq = _mali_osk_irq_init(resource->irq,
  101. mali_group_upper_half_mmu,
  102. group,
  103. mali_mmu_probe_trigger,
  104. mali_mmu_probe_ack,
  105. mmu,
  106. resource->description);
  107. if (NULL != mmu->irq) {
  108. return mmu;
  109. } else {
  110. MALI_PRINT_ERROR(("Mali MMU: Failed to setup interrupt handlers for MMU %s\n", mmu->hw_core.description));
  111. }
  112. }
  113. mali_group_remove_mmu_core(group);
  114. } else {
  115. MALI_PRINT_ERROR(("Mali MMU: Failed to add core %s to group\n", mmu->hw_core.description));
  116. }
  117. mali_hw_core_delete(&mmu->hw_core);
  118. }
  119. _mali_osk_free(mmu);
  120. } else {
  121. MALI_PRINT_ERROR(("Failed to allocate memory for MMU\n"));
  122. }
  123. return NULL;
  124. }
  125. void mali_mmu_delete(struct mali_mmu_core *mmu)
  126. {
  127. if (NULL != mmu->irq) {
  128. _mali_osk_irq_term(mmu->irq);
  129. }
  130. mali_hw_core_delete(&mmu->hw_core);
  131. _mali_osk_free(mmu);
  132. }
  133. static void mali_mmu_enable_paging(struct mali_mmu_core *mmu)
  134. {
  135. int i;
  136. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING);
  137. for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) {
  138. if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_PAGING_ENABLED) {
  139. break;
  140. }
  141. }
  142. if (MALI_REG_POLL_COUNT_FAST == i) {
  143. MALI_PRINT_ERROR(("Enable paging request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
  144. }
  145. }
  146. /**
  147. * Issues the enable stall command to the MMU and waits for HW to complete the request
  148. * @param mmu The MMU to enable paging for
  149. * @return MALI_TRUE if HW stall was successfully engaged, otherwise MALI_FALSE (req timed out)
  150. */
  151. static mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu)
  152. {
  153. int i;
  154. u32 mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
  155. if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED) ) {
  156. MALI_DEBUG_PRINT(4, ("MMU stall is implicit when Paging is not enabled.\n"));
  157. return MALI_TRUE;
  158. }
  159. if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) {
  160. MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it is in pagefault state.\n"));
  161. return MALI_FALSE;
  162. }
  163. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL);
  164. for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) {
  165. mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
  166. if (mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) {
  167. break;
  168. }
  169. if ((mmu_status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) && (0 == (mmu_status & MALI_MMU_STATUS_BIT_STALL_NOT_ACTIVE))) {
  170. break;
  171. }
  172. if (0 == (mmu_status & ( MALI_MMU_STATUS_BIT_PAGING_ENABLED ))) {
  173. break;
  174. }
  175. }
  176. if (MALI_REG_POLL_COUNT_FAST == i) {
  177. MALI_DEBUG_PRINT(2, ("Enable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
  178. return MALI_FALSE;
  179. }
  180. if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) {
  181. MALI_DEBUG_PRINT(2, ("Aborting MMU stall request since it has a pagefault.\n"));
  182. return MALI_FALSE;
  183. }
  184. return MALI_TRUE;
  185. }
  186. /**
  187. * Issues the disable stall command to the MMU and waits for HW to complete the request
  188. * @param mmu The MMU to enable paging for
  189. */
  190. static void mali_mmu_disable_stall(struct mali_mmu_core *mmu)
  191. {
  192. int i;
  193. u32 mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
  194. if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED )) {
  195. MALI_DEBUG_PRINT(3, ("MMU disable skipped since it was not enabled.\n"));
  196. return;
  197. }
  198. if (mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) {
  199. MALI_DEBUG_PRINT(2, ("Aborting MMU disable stall request since it is in pagefault state.\n"));
  200. return;
  201. }
  202. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL);
  203. for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) {
  204. u32 status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
  205. if ( 0 == (status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) ) {
  206. break;
  207. }
  208. if ( status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) {
  209. break;
  210. }
  211. if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED )) {
  212. break;
  213. }
  214. }
  215. if (MALI_REG_POLL_COUNT_FAST == i) MALI_DEBUG_PRINT(1,("Disable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
  216. }
  217. void mali_mmu_page_fault_done(struct mali_mmu_core *mmu)
  218. {
  219. MALI_DEBUG_PRINT(4, ("Mali MMU: %s: Leaving page fault mode\n", mmu->hw_core.description));
  220. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_PAGE_FAULT_DONE);
  221. }
  222. MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu)
  223. {
  224. int i;
  225. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, 0xCAFEBABE);
  226. MALI_DEBUG_ASSERT(0xCAFEB000 == mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR));
  227. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_HARD_RESET);
  228. for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) {
  229. if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR) == 0) {
  230. break;
  231. }
  232. }
  233. if (MALI_REG_POLL_COUNT_FAST == i) {
  234. MALI_PRINT_ERROR(("Reset request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
  235. return _MALI_OSK_ERR_FAULT;
  236. }
  237. return _MALI_OSK_ERR_OK;
  238. }
  239. _mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu)
  240. {
  241. _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
  242. mali_bool stall_success;
  243. MALI_DEBUG_ASSERT_POINTER(mmu);
  244. stall_success = mali_mmu_enable_stall(mmu);
  245. if (!stall_success) {
  246. err = _MALI_OSK_ERR_BUSY;
  247. }
  248. MALI_DEBUG_PRINT(3, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->hw_core.description));
  249. if (_MALI_OSK_ERR_OK == mali_mmu_raw_reset(mmu)) {
  250. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
  251. /* no session is active, so just activate the empty page directory */
  252. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory_phys);
  253. mali_mmu_enable_paging(mmu);
  254. err = _MALI_OSK_ERR_OK;
  255. }
  256. mali_mmu_disable_stall(mmu);
  257. return err;
  258. }
  259. mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu)
  260. {
  261. mali_bool stall_success = mali_mmu_enable_stall(mmu);
  262. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
  263. if (MALI_FALSE == stall_success) {
  264. /* False means that it is in Pagefault state. Not possible to disable_stall then */
  265. return MALI_FALSE;
  266. }
  267. mali_mmu_disable_stall(mmu);
  268. return MALI_TRUE;
  269. }
  270. void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu)
  271. {
  272. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
  273. }
  274. void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address)
  275. {
  276. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_ZAP_ONE_LINE, MALI_MMU_PDE_ENTRY(mali_address));
  277. }
  278. static void mali_mmu_activate_address_space(struct mali_mmu_core *mmu, u32 page_directory)
  279. {
  280. /* The MMU must be in stalled or page fault mode, for this writing to work */
  281. MALI_DEBUG_ASSERT( 0 != ( mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)
  282. & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) );
  283. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, page_directory);
  284. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
  285. }
  286. void mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mali_page_directory *pagedir)
  287. {
  288. mali_bool stall_success;
  289. MALI_DEBUG_ASSERT_POINTER(mmu);
  290. MALI_DEBUG_PRINT(5, ("Asked to activate page directory 0x%x on MMU %s\n", pagedir, mmu->hw_core.description));
  291. stall_success = mali_mmu_enable_stall(mmu);
  292. MALI_DEBUG_ASSERT(stall_success);
  293. MALI_IGNORE(stall_success);
  294. mali_mmu_activate_address_space(mmu, pagedir->page_directory);
  295. mali_mmu_disable_stall(mmu);
  296. }
  297. void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu)
  298. {
  299. mali_bool stall_success;
  300. MALI_DEBUG_ASSERT_POINTER(mmu);
  301. MALI_DEBUG_PRINT(3, ("Activating the empty page directory on MMU %s\n", mmu->hw_core.description));
  302. stall_success = mali_mmu_enable_stall(mmu);
  303. /* This function can only be called when the core is idle, so it could not fail. */
  304. MALI_DEBUG_ASSERT(stall_success);
  305. MALI_IGNORE(stall_success);
  306. mali_mmu_activate_address_space(mmu, mali_empty_page_directory_phys);
  307. mali_mmu_disable_stall(mmu);
  308. }
  309. void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu)
  310. {
  311. mali_bool stall_success;
  312. MALI_DEBUG_ASSERT_POINTER(mmu);
  313. MALI_DEBUG_PRINT(3, ("Activating the page fault flush page directory on MMU %s\n", mmu->hw_core.description));
  314. stall_success = mali_mmu_enable_stall(mmu);
  315. /* This function is expect to fail the stalling, since it might be in PageFault mode when it is called */
  316. mali_mmu_activate_address_space(mmu, mali_page_fault_flush_page_directory);
  317. if ( MALI_TRUE==stall_success ) mali_mmu_disable_stall(mmu);
  318. }
  319. /* Is called when we want the mmu to give an interrupt */
  320. static void mali_mmu_probe_trigger(void *data)
  321. {
  322. struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
  323. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT, MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR);
  324. }
  325. /* Is called when the irq probe wants the mmu to acknowledge an interrupt from the hw */
  326. static _mali_osk_errcode_t mali_mmu_probe_ack(void *data)
  327. {
  328. struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
  329. u32 int_stat;
  330. int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS);
  331. MALI_DEBUG_PRINT(2, ("mali_mmu_probe_irq_acknowledge: intstat 0x%x\n", int_stat));
  332. if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT) {
  333. MALI_DEBUG_PRINT(2, ("Probe: Page fault detect: PASSED\n"));
  334. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_PAGE_FAULT);
  335. } else {
  336. MALI_DEBUG_PRINT(1, ("Probe: Page fault detect: FAILED\n"));
  337. }
  338. if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR) {
  339. MALI_DEBUG_PRINT(2, ("Probe: Bus read error detect: PASSED\n"));
  340. mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR);
  341. } else {
  342. MALI_DEBUG_PRINT(1, ("Probe: Bus read error detect: FAILED\n"));
  343. }
  344. if ( (int_stat & (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) ==
  345. (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) {
  346. return _MALI_OSK_ERR_OK;
  347. }
  348. return _MALI_OSK_ERR_FAULT;
  349. }
  350. #if 0
  351. void mali_mmu_print_state(struct mali_mmu_core *mmu)
  352. {
  353. MALI_DEBUG_PRINT(2, ("MMU: State of %s is 0x%08x\n", mmu->hw_core.description, mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
  354. }
  355. #endif