xref: /haiku/src/system/kernel/arch/m68k/paging/M68KVMTranslationMap.cpp (revision 385ee03ba83b7a40d315e17b03031b3ca37820c0)
1 /*
2  * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
4  * Distributed under the terms of the MIT License.
5  *
6  * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
7  * Distributed under the terms of the NewOS License.
8  */
9 
10 
11 #include "paging/M68KVMTranslationMap.h"
12 
13 #include <thread.h>
14 #include <smp.h>
15 
16 #include "paging/M68KPagingStructures.h"
17 
18 
19 //#define TRACE_M68K_VM_TRANSLATION_MAP
20 #ifdef TRACE_M68K_VM_TRANSLATION_MAP
21 #	define TRACE(x...) dprintf(x)
22 #else
23 #	define TRACE(x...) ;
24 #endif
25 
26 
27 M68KVMTranslationMap::M68KVMTranslationMap()
28 	:
29 	fPageMapper(NULL),
30 	fInvalidPagesCount(0)
31 {
32 }
33 
34 
35 M68KVMTranslationMap::~M68KVMTranslationMap()
36 {
37 }
38 
39 
40 status_t
41 M68KVMTranslationMap::Init(bool kernel)
42 {
43 	fIsKernelMap = kernel;
44 	return B_OK;
45 }
46 
47 
48 /*!	Acquires the map's recursive lock, and resets the invalidate pages counter
49 	in case it's the first locking recursion.
50 */
51 bool
52 M68KVMTranslationMap::Lock()
53 {
54 	TRACE("%p->M68KVMTranslationMap::Lock()\n", this);
55 
56 	recursive_lock_lock(&fLock);
57 	if (recursive_lock_get_recursion(&fLock) == 1) {
58 		// we were the first one to grab the lock
59 		TRACE("clearing invalidated page count\n");
60 		fInvalidPagesCount = 0;
61 	}
62 
63 	return true;
64 }
65 
66 
67 /*!	Unlocks the map, and, if we are actually losing the recursive lock,
68 	flush all pending changes of this map (ie. flush TLB caches as
69 	needed).
70 */
71 void
72 M68KVMTranslationMap::Unlock()
73 {
74 	TRACE("%p->M68KVMTranslationMap::Unlock()\n", this);
75 
76 	if (recursive_lock_get_recursion(&fLock) == 1) {
77 		// we're about to release it for the last time
78 		Flush();
79 	}
80 
81 	recursive_lock_unlock(&fLock);
82 }
83 
84 
85 addr_t
86 M68KVMTranslationMap::MappedSize() const
87 {
88 	return fMapCount;
89 }
90 
91 
92 void
93 M68KVMTranslationMap::Flush()
94 {
95 	if (fInvalidPagesCount <= 0)
96 		return;
97 
98 	Thread* thread = thread_get_current_thread();
99 	thread_pin_to_current_cpu(thread);
100 
101 	if (fInvalidPagesCount > PAGE_INVALIDATE_CACHE_SIZE) {
102 		// invalidate all pages
103 		TRACE("flush_tmap: %d pages to invalidate, invalidate all\n",
104 			fInvalidPagesCount);
105 
106 		if (fIsKernelMap) {
107 			arch_cpu_global_TLB_invalidate();
108 			smp_send_broadcast_ici(SMP_MSG_GLOBAL_INVALIDATE_PAGES, 0, 0, 0,
109 				NULL, SMP_MSG_FLAG_SYNC);
110 		} else {
111 			cpu_status state = disable_interrupts();
112 			arch_cpu_user_TLB_invalidate();
113 			restore_interrupts(state);
114 
115 			int cpu = smp_get_current_cpu();
116 			CPUSet cpuMask = PagingStructures()->active_on_cpus;
117 			cpuMask.ClearBit(cpu);
118 
119 			if (!cpuMask.IsEmpty()) {
120 				smp_send_multicast_ici(cpuMask, SMP_MSG_USER_INVALIDATE_PAGES,
121 					0, 0, 0, NULL, SMP_MSG_FLAG_SYNC);
122 			}
123 		}
124 	} else {
125 		TRACE("flush_tmap: %d pages to invalidate, invalidate list\n",
126 			fInvalidPagesCount);
127 
128 		arch_cpu_invalidate_TLB_list(fInvalidPages, fInvalidPagesCount);
129 
130 		if (fIsKernelMap) {
131 			smp_send_broadcast_ici(SMP_MSG_INVALIDATE_PAGE_LIST,
132 				(addr_t)fInvalidPages, fInvalidPagesCount, 0, NULL,
133 				SMP_MSG_FLAG_SYNC);
134 		} else {
135 			int cpu = smp_get_current_cpu();
136 			CPUSet cpuMask = PagingStructures()->active_on_cpus;
137 			cpuMask.ClearBit(cpu);
138 
139 			if (!cpuMask.IsEmpty()) {
140 				smp_send_multicast_ici(cpuMask, SMP_MSG_INVALIDATE_PAGE_LIST,
141 					(addr_t)fInvalidPages, fInvalidPagesCount, 0, NULL,
142 					SMP_MSG_FLAG_SYNC);
143 			}
144 		}
145 	}
146 	fInvalidPagesCount = 0;
147 
148 	thread_unpin_from_current_cpu(thread);
149 }
150