From df5b7147f47ae3bca23bde18f3d432f5ce26a2ff Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 4 Dec 2023 13:26:07 +0100 Subject: [PATCH] udebug: add mips specific quirk On some MIPS systems, mmap addresses need to be aligned to multiple pages, in order to avoid issues with data cache aliases. Add an arch specific quirk to allocate memory in 32 KiB chunks and align addresses returned by mmap. Signed-off-by: Felix Fietkau --- udebug.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/udebug.c b/udebug.c index 0d8d0d4..81afc78 100644 --- a/udebug.c +++ b/udebug.c @@ -37,6 +37,7 @@ #define UDEBUG_MIN_ALLOC_LEN 128 static struct blob_buf b; +static unsigned int page_size; static void __randname(char *template) { @@ -114,13 +115,21 @@ uint64_t udebug_timestamp(void) static int __udebug_buf_map(struct udebug_buf *buf) { + unsigned int pad = 0; void *ptr, *ptr2; - ptr = mmap(NULL, buf->head_size + 2 * buf->data_size, PROT_NONE, +#ifdef mips + pad = page_size; +#endif + ptr = mmap(NULL, buf->head_size + 2 * buf->data_size + pad, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (ptr == MAP_FAILED) return -1; +#ifdef mips + ptr = (void *)ALIGN((unsigned long)ptr, page_size); +#endif + ptr2 = mmap(ptr, buf->head_size + buf->data_size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, buf->fd, 0); if (ptr2 != ptr) @@ -394,18 +403,31 @@ udebug_buf_msg(struct udebug_buf *buf, enum udebug_client_msg_type type) udebug_wait_for_response(buf->ctx, &msg, NULL); } -static size_t __udebug_headsize(unsigned int ring_size, unsigned int page_size) +static size_t __udebug_headsize(unsigned int ring_size) { ring_size *= sizeof(struct udebug_ptr); return ALIGN(sizeof(struct udebug_hdr) + ring_size, page_size); } +static void udebug_init_page_size(void) +{ + if (page_size) + return; + page_size = sysconf(_SC_PAGESIZE); +#ifdef mips + /* leave extra alignment room to account for data cache aliases */ + if (page_size < 32 * 1024) + page_size = 32 * 1024; +#endif +} + int udebug_buf_open(struct udebug_buf *buf, int fd, uint32_t ring_size, uint32_t data_size) { + udebug_init_page_size(); INIT_LIST_HEAD(&buf->list); buf->fd = fd; buf->ring_size = ring_size; - buf->head_size = __udebug_headsize(ring_size, sysconf(_SC_PAGESIZE)); + buf->head_size = __udebug_headsize(ring_size); buf->data_size = data_size; if (buf->ring_size > (1U << 24) || buf->data_size > (1U << 29)) @@ -426,16 +448,16 @@ int udebug_buf_open(struct udebug_buf *buf, int fd, uint32_t ring_size, uint32_t int udebug_buf_init(struct udebug_buf *buf, size_t entries, size_t size) { - uint32_t pagesz = sysconf(_SC_PAGESIZE); char filename[] = "/udebug.XXXXXX"; unsigned int order = 12; uint8_t ring_order = 5; size_t head_size; int fd; + udebug_init_page_size(); INIT_LIST_HEAD(&buf->list); - if (size < pagesz) - size = pagesz; + if (size < page_size) + size = page_size; while(size > 1U << order) order++; size = 1 << order; @@ -446,8 +468,8 @@ int udebug_buf_init(struct udebug_buf *buf, size_t entries, size_t size) if (size > (1U << 29) || entries > (1U << 24)) return -1; - head_size = __udebug_headsize(entries, pagesz); - while (ALIGN(sizeof(*buf->hdr) + (entries * 2) * sizeof(struct udebug_ptr), pagesz) == head_size) + head_size = __udebug_headsize(entries); + while (ALIGN(sizeof(*buf->hdr) + (entries * 2) * sizeof(struct udebug_ptr), page_size) == head_size) entries *= 2; fd = shm_open_anon(filename);