Skip to content

Commit 629979c

Browse files
committed
[DEB] userspace: Print component memory domain
1 parent ea4ca0e commit 629979c

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
@@ -27,13 +27,17 @@
2727
#include <zephyr/kernel.h>
2828
#include <zephyr/app_memory/app_memdomain.h>
2929
#include <zephyr/logging/log.h>
30+
#include <../../../../../zephyr/zephyr/arch/xtensa/include/xtensa_mmu_priv.h>
31+
#include <zephyr/arch/xtensa/xtensa_mmu.h>
3032

3133
LOG_MODULE_REGISTER(userspace_helper, CONFIG_SOF_LOG_LEVEL);
3234

3335
#if CONFIG_USERSPACE
3436

3537
K_APPMEM_PARTITION_DEFINE(common_partition);
3638

39+
extern struct tr_ctx userspace_proxy_tr;
40+
3741
struct k_heap *module_driver_heap_init(void)
3842
{
3943
struct k_heap *mod_drv_heap = rballoc(SOF_MEM_FLAG_USER, sizeof(*mod_drv_heap));
@@ -149,6 +153,171 @@ void user_grant_dma_access_all(struct k_thread *thread)
149153

150154
#endif /* CONFIG_SOF_USERSPACE_LL */
151155

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

154323
void *user_stack_allocate(size_t stack_size, uint32_t options)

0 commit comments

Comments
 (0)