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 <nbd@nbd.name>
This commit is contained in:
Felix Fietkau 2023-12-04 13:26:07 +01:00
parent d27acfe416
commit df5b7147f4

View file

@ -37,6 +37,7 @@
#define UDEBUG_MIN_ALLOC_LEN 128 #define UDEBUG_MIN_ALLOC_LEN 128
static struct blob_buf b; static struct blob_buf b;
static unsigned int page_size;
static void __randname(char *template) static void __randname(char *template)
{ {
@ -114,13 +115,21 @@ uint64_t udebug_timestamp(void)
static int static int
__udebug_buf_map(struct udebug_buf *buf) __udebug_buf_map(struct udebug_buf *buf)
{ {
unsigned int pad = 0;
void *ptr, *ptr2; 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); MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (ptr == MAP_FAILED) if (ptr == MAP_FAILED)
return -1; return -1;
#ifdef mips
ptr = (void *)ALIGN((unsigned long)ptr, page_size);
#endif
ptr2 = mmap(ptr, buf->head_size + buf->data_size, ptr2 = mmap(ptr, buf->head_size + buf->data_size,
PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, buf->fd, 0); PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, buf->fd, 0);
if (ptr2 != ptr) 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); 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); ring_size *= sizeof(struct udebug_ptr);
return ALIGN(sizeof(struct udebug_hdr) + ring_size, page_size); 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) 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); INIT_LIST_HEAD(&buf->list);
buf->fd = fd; buf->fd = fd;
buf->ring_size = ring_size; 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; buf->data_size = data_size;
if (buf->ring_size > (1U << 24) || buf->data_size > (1U << 29)) 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) int udebug_buf_init(struct udebug_buf *buf, size_t entries, size_t size)
{ {
uint32_t pagesz = sysconf(_SC_PAGESIZE);
char filename[] = "/udebug.XXXXXX"; char filename[] = "/udebug.XXXXXX";
unsigned int order = 12; unsigned int order = 12;
uint8_t ring_order = 5; uint8_t ring_order = 5;
size_t head_size; size_t head_size;
int fd; int fd;
udebug_init_page_size();
INIT_LIST_HEAD(&buf->list); INIT_LIST_HEAD(&buf->list);
if (size < pagesz) if (size < page_size)
size = pagesz; size = page_size;
while(size > 1U << order) while(size > 1U << order)
order++; order++;
size = 1 << 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)) if (size > (1U << 29) || entries > (1U << 24))
return -1; return -1;
head_size = __udebug_headsize(entries, pagesz); head_size = __udebug_headsize(entries);
while (ALIGN(sizeof(*buf->hdr) + (entries * 2) * sizeof(struct udebug_ptr), pagesz) == head_size) while (ALIGN(sizeof(*buf->hdr) + (entries * 2) * sizeof(struct udebug_ptr), page_size) == head_size)
entries *= 2; entries *= 2;
fd = shm_open_anon(filename); fd = shm_open_anon(filename);