Skip to content

Commit 8e7922d

Browse files
committed
[DEB] userspace: Print component memory domain
1 parent 4892444 commit 8e7922d

2 files changed

Lines changed: 179 additions & 0 deletions

File tree

zephyr/include/rtos/userspace_helper.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,4 +137,14 @@ static inline int user_access_to_mailbox(struct k_mem_domain *domain, k_tid_t th
137137

138138
#endif /* CONFIG_USERSPACE */
139139

140+
void dump_memory_domain(struct k_mem_domain *domain);
141+
void dump_page_tables(uint32_t *ptables, void *test, bool kernel);
142+
void dump_page_table(uint32_t *ptables, void *test);
143+
void dump_domain_page_tables(struct k_mem_domain *domain, void *test, bool kernel);
144+
145+
static inline void dump_domain_entry(struct k_mem_domain *domain, void *test)
146+
{
147+
dump_page_tables(domain->arch.ptables, test, false);
148+
}
149+
140150
#endif /* __ZEPHYR_LIB_USERSPACE_HELPER_H__ */

zephyr/lib/userspace_helper.c

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,17 @@
2929
#include <zephyr/kernel.h>
3030
#include <zephyr/app_memory/app_memdomain.h>
3131
#include <zephyr/logging/log.h>
32+
#include <../../../../../zephyr/zephyr/arch/xtensa/include/xtensa_mmu_priv.h>
33+
#include <zephyr/arch/xtensa/xtensa_mmu.h>
3234

3335
LOG_MODULE_REGISTER(userspace_helper, CONFIG_SOF_LOG_LEVEL);
3436

3537
#if CONFIG_USERSPACE
3638

3739
K_APPMEM_PARTITION_DEFINE(common_partition);
3840

41+
extern struct tr_ctx userspace_proxy_tr;
42+
3943
struct k_heap *module_driver_heap_init(void)
4044
{
4145
struct k_heap *mod_drv_heap = rballoc(SOF_MEM_FLAG_USER, sizeof(*mod_drv_heap));
@@ -151,6 +155,171 @@ void user_grant_dma_access_all(struct k_thread *thread)
151155

152156
#endif /* CONFIG_SOF_USERSPACE_LL */
153157

158+
/** Mask for attributes in PTE */
159+
#define PTE_ATTR_MASK 0x0000000FU
160+
161+
/** Number of bits to shift for attributes in PTE */
162+
#define PTE_ATTR_SHIFT 0U
163+
164+
/** Mask for cache mode in PTE */
165+
#define PTE_ATTR_CACHED_MASK 0x0000000CU
166+
167+
/** Mask for ring in PTE */
168+
#define PTE_RING_MASK 0x00000030U
169+
170+
/** Number of bits to shift for ring in PTE */
171+
#define PTE_RING_SHIFT 4U
172+
173+
/** Number of bits to shift for backup attributes in PTE SW field. */
174+
#define PTE_BCKUP_ATTR_SHIFT (PTE_ATTR_SHIFT + 6U)
175+
176+
/** Mask for backup attributes in PTE SW field. */
177+
#define PTE_BCKUP_ATTR_MASK (PTE_ATTR_MASK << 6U)
178+
179+
/** Number of bits to shift for backup ring value in PTE SW field. */
180+
#define PTE_BCKUP_RING_SHIFT (PTE_RING_SHIFT + 6U)
181+
182+
/** Mask for backup ring value in PTE SW field. */
183+
#define PTE_BCKUP_RING_MASK (PTE_RING_MASK << 6U)
184+
185+
/** Combined attributes and ring mask in PTE. */
186+
#define PTE_PERM_MASK (PTE_ATTR_MASK | PTE_RING_MASK)
187+
188+
/** Number of bits to shift for combined attributes and ring in PTE. */
189+
#define PTE_PERM_SHIFT 0U
190+
191+
/** Combined backup attributes and backup ring mask in PTE. */
192+
#define PTE_BCKUP_PERM_MASK (PTE_BCKUP_ATTR_MASK | PTE_BCKUP_RING_MASK)
193+
194+
/** Number of bits to shift for combined backup attributes and backup ring mask in PTE. */
195+
#define PTE_BCKUP_PERM_SHIFT 6U
196+
197+
#define PTE_ATTR_ILLEGAL (BIT(3) | BIT(2))
198+
199+
/** Get the ring from a PTE */
200+
#define PTE_RING_GET(pte) (((pte) & PTE_RING_MASK) >> PTE_RING_SHIFT)
201+
202+
/** Get the permissions from a PTE */
203+
#define PTE_PERM_GET(pte) (((pte) & PTE_PERM_MASK) >> PTE_PERM_SHIFT)
204+
205+
/** Get the backup permissions from a PTE */
206+
#define PTE_BCKUP_PERM_GET(pte) (((pte) & PTE_BCKUP_PERM_MASK) >> PTE_BCKUP_PERM_SHIFT)
207+
208+
/** Get the backed up attributes from the PTE SW field. */
209+
#define PTE_BCKUP_ATTR_GET(pte) (((pte) & PTE_BCKUP_ATTR_MASK) >> PTE_BCKUP_ATTR_SHIFT)
210+
211+
/** Get the backed up ring value from the PTE SW field. */
212+
#define PTE_BCKUP_RING_GET(pte) (((pte) & PTE_BCKUP_RING_MASK) >> PTE_BCKUP_RING_SHIFT)
213+
214+
static void dump_pte_attr(char *attr_s, uint32_t attr)
215+
{
216+
attr_s[0] = attr & XTENSA_MMU_CACHED_WT ? 'T' : '-';
217+
attr_s[1] = attr & XTENSA_MMU_CACHED_WB ? 'B' : '-';
218+
attr_s[2] = attr & XTENSA_MMU_PERM_W ? 'W' : '-';
219+
attr_s[3] = attr & XTENSA_MMU_PERM_X ? 'X' : '-';
220+
attr_s[4] = '\0';
221+
}
222+
223+
static uint32_t *dump_pte(uint32_t pte)
224+
{
225+
uint32_t ppn = pte & XTENSA_MMU_PTE_PPN_MASK;
226+
uint32_t ring = PTE_RING_GET(pte);
227+
uint32_t sw = PTE_BCKUP_PERM_GET(pte);
228+
uint32_t sw_ring = PTE_BCKUP_RING_GET(pte);
229+
uint32_t sw_attr = PTE_BCKUP_ATTR_GET(pte);
230+
uint32_t attr = PTE_PERM_GET(pte);
231+
232+
char attr_s[5];
233+
dump_pte_attr(attr_s, attr);
234+
235+
char sw_attr_s[5];
236+
dump_pte_attr(sw_attr_s, sw_attr);
237+
238+
tr_err(&userspace_proxy_tr, "PPN %#x, sw %#x (ring: %u, %s), ring %u %s",
239+
ppn, sw, sw_ring, sw_attr_s, ring, attr_s);
240+
241+
if ((attr & PTE_ATTR_ILLEGAL) == PTE_ATTR_ILLEGAL) {
242+
//tr_err(&userspace_proxy_tr, "ILLEGAL PTE");
243+
return NULL;
244+
}
245+
246+
return (uint32_t *)ppn;
247+
}
248+
249+
void dump_page_table(uint32_t *ptables, void *test)
250+
{
251+
const uint32_t l1_index = XTENSA_MMU_L1_POS(POINTER_TO_UINT(test));
252+
const uint32_t l2_index = XTENSA_MMU_L2_POS(POINTER_TO_UINT(test));
253+
const uint32_t test_aligned = POINTER_TO_UINT(test) & ~(CONFIG_MMU_PAGE_SIZE - 1);
254+
255+
tr_err(&userspace_proxy_tr, "test %p, ptables = %p, L1 = %#x, L2 = %#x", test,
256+
(void *)ptables, l1_index, l2_index);
257+
258+
uint32_t *const l1_entry = ptables + l1_index;
259+
//tr_err(&userspace_proxy_tr, "l1 @ %p = %p", (void *)l1_entry, *l1_entry);
260+
261+
uint32_t* l1_ppn = dump_pte(*l1_entry);
262+
if (!l1_ppn) {
263+
tr_err(&userspace_proxy_tr, "INVALID L1 PTE!");
264+
return;
265+
}
266+
267+
uint32_t *const l2_entry = l1_ppn + l2_index;
268+
//tr_err(&userspace_proxy_tr, "l2 @ %p = %p", (void *)l2_entry, *l2_entry);
269+
uint32_t *l2_ppn = dump_pte(*l2_entry);
270+
271+
if (test_aligned != POINTER_TO_UINT(l2_ppn)) {
272+
tr_err(&userspace_proxy_tr, "INVALID L2 PTE!");
273+
return;
274+
}
275+
}
276+
277+
extern uint32_t *xtensa_kernel_ptables;
278+
279+
void dump_page_tables(uint32_t *ptables, void *test, bool kernel)
280+
{
281+
if (ptables) {
282+
tr_err(&userspace_proxy_tr, "Dump for %p in user table", test);
283+
dump_page_table(ptables, sys_cache_cached_ptr_get(test));
284+
dump_page_table(ptables, sys_cache_uncached_ptr_get(test));
285+
}
286+
287+
if (kernel) {
288+
tr_err(&userspace_proxy_tr, "Kernel table", test);
289+
dump_page_table(xtensa_kernel_ptables, sys_cache_cached_ptr_get(test));
290+
dump_page_table(xtensa_kernel_ptables, sys_cache_uncached_ptr_get(test));
291+
}
292+
}
293+
294+
void dump_domain_page_tables(struct k_mem_domain *domain, void *test, bool kernel)
295+
{
296+
dump_page_tables(domain->arch.ptables, test, kernel);
297+
}
298+
299+
static void dump_domain_attr(char *attr_s, uint32_t attr)
300+
{
301+
attr_s[0] = attr & XTENSA_MMU_MAP_SHARED ? 'S' : '-';
302+
attr_s[1] = K_MEM_PARTITION_IS_USER(attr) ? 'U' : '-';
303+
dump_pte_attr(attr_s + 2, attr);
304+
}
305+
306+
void dump_memory_domain(struct k_mem_domain *domain)
307+
{
308+
int i;
309+
char attrs[7];
310+
311+
for (i = 0; i < domain->num_partitions; i++) {
312+
dump_domain_attr(attrs, domain->partitions[i].attr);
313+
314+
tr_err(&userspace_proxy_tr, "partitions[%d]: %p + %#zx %s", i,
315+
UINT_TO_POINTER(domain->partitions[i].start),
316+
domain->partitions[i].size, attrs);
317+
}
318+
319+
tr_err(&userspace_proxy_tr, "ptables = %p, asid = %u, dirty = %u",
320+
(void *)domain->arch.ptables, domain->arch.asid, domain->arch.dirty);
321+
}
322+
154323
#else /* CONFIG_USERSPACE */
155324

156325
void *user_stack_allocate(size_t stack_size, uint32_t options)

0 commit comments

Comments
 (0)