source: mainline/kernel/arch/sparc64/src/mm/as.c@ 7cb567cd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7cb567cd was 879585a3, checked in by Jakub Jermar <jakub@…>, 19 years ago

Simplify synchronization in as_switch().
The function was oversynchronized, which
was causing deadlocks on the address
space mutex.

Now, address spaces can only be switched
when the asidlock is held. This also protects
stealing of ASIDs. No other synchronization
is necessary.

  • Property mode set to 100644
File size: 5.4 KB
Line 
1/*
2 * Copyright (c) 2006 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup sparc64mm
30 * @{
31 */
32/** @file
33 */
34
35#include <arch/mm/as.h>
36#include <arch/mm/tlb.h>
37#include <genarch/mm/page_ht.h>
38#include <genarch/mm/asid_fifo.h>
39#include <debug.h>
40#include <config.h>
41
42#ifdef CONFIG_TSB
43#include <arch/mm/tsb.h>
44#include <arch/memstr.h>
45#include <arch/asm.h>
46#include <mm/frame.h>
47#include <bitops.h>
48#include <macros.h>
49#endif /* CONFIG_TSB */
50
51/** Architecture dependent address space init. */
52void as_arch_init(void)
53{
54 if (config.cpu_active == 1) {
55 as_operations = &as_ht_operations;
56 asid_fifo_init();
57 }
58}
59
60int as_constructor_arch(as_t *as, int flags)
61{
62#ifdef CONFIG_TSB
63 /*
64 * The order must be calculated with respect to the emulated
65 * 16K page size.
66 */
67 int order = fnzb32(((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
68 sizeof(tsb_entry_t)) >> FRAME_WIDTH);
69 uintptr_t tsb = (uintptr_t) frame_alloc(order, flags | FRAME_KA);
70
71 if (!tsb)
72 return -1;
73
74 as->arch.itsb = (tsb_entry_t *) tsb;
75 as->arch.dtsb = (tsb_entry_t *) (tsb + ITSB_ENTRY_COUNT *
76 sizeof(tsb_entry_t));
77 memsetb((uintptr_t) as->arch.itsb,
78 (ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * sizeof(tsb_entry_t), 0);
79#endif
80 return 0;
81}
82
83int as_destructor_arch(as_t *as)
84{
85#ifdef CONFIG_TSB
86 /*
87 * The count must be calculated with respect to the emualted 16K page
88 * size.
89 */
90 count_t cnt = ((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
91 sizeof(tsb_entry_t)) >> FRAME_WIDTH;
92 frame_free(KA2PA((uintptr_t) as->arch.itsb));
93 return cnt;
94#else
95 return 0;
96#endif
97}
98
99int as_create_arch(as_t *as, int flags)
100{
101#ifdef CONFIG_TSB
102 tsb_invalidate(as, 0, (count_t) -1);
103#endif
104 return 0;
105}
106
107/** Perform sparc64-specific tasks when an address space becomes active on the
108 * processor.
109 *
110 * Install ASID and map TSBs.
111 *
112 * @param as Address space.
113 */
114void as_install_arch(as_t *as)
115{
116 tlb_context_reg_t ctx;
117
118 /*
119 * Note that we don't and may not lock the address space. That's ok
120 * since we only read members that are currently read-only.
121 *
122 * Moreover, the as->asid is protected by asidlock, which is being held.
123 */
124
125 /*
126 * Write ASID to secondary context register. The primary context
127 * register has to be set from TL>0 so it will be filled from the
128 * secondary context register from the TL=1 code just before switch to
129 * userspace.
130 */
131 ctx.v = 0;
132 ctx.context = as->asid;
133 mmu_secondary_context_write(ctx.v);
134
135#ifdef CONFIG_TSB
136 uintptr_t base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH);
137
138 ASSERT(as->arch.itsb && as->arch.dtsb);
139
140 uintptr_t tsb = (uintptr_t) as->arch.itsb;
141
142 if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
143 /*
144 * TSBs were allocated from memory not covered
145 * by the locked 4M kernel DTLB entry. We need
146 * to map both TSBs explicitly.
147 */
148 dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, tsb);
149 dtlb_insert_mapping(tsb, KA2PA(tsb), PAGESIZE_64K, true, true);
150 }
151
152 /*
153 * Setup TSB Base registers.
154 */
155 tsb_base_reg_t tsb_base;
156
157 tsb_base.value = 0;
158 tsb_base.size = TSB_SIZE;
159 tsb_base.split = 0;
160
161 tsb_base.base = ((uintptr_t) as->arch.itsb) >> MMU_PAGE_WIDTH;
162 itsb_base_write(tsb_base.value);
163 tsb_base.base = ((uintptr_t) as->arch.dtsb) >> MMU_PAGE_WIDTH;
164 dtsb_base_write(tsb_base.value);
165#endif
166}
167
168/** Perform sparc64-specific tasks when an address space is removed from the
169 * processor.
170 *
171 * Demap TSBs.
172 *
173 * @param as Address space.
174 */
175void as_deinstall_arch(as_t *as)
176{
177
178 /*
179 * Note that we don't and may not lock the address space. That's ok
180 * since we only read members that are currently read-only.
181 *
182 * Moreover, the as->asid is protected by asidlock, which is being held.
183 */
184
185#ifdef CONFIG_TSB
186 uintptr_t base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH);
187
188 ASSERT(as->arch.itsb && as->arch.dtsb);
189
190 uintptr_t tsb = (uintptr_t) as->arch.itsb;
191
192 if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
193 /*
194 * TSBs were allocated from memory not covered
195 * by the locked 4M kernel DTLB entry. We need
196 * to demap the entry installed by as_install_arch().
197 */
198 dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, tsb);
199 }
200#endif
201}
202
203/** @}
204 */
Note: See TracBrowser for help on using the repository browser.