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:
parent
d27acfe416
commit
df5b7147f4
1 changed files with 30 additions and 8 deletions
38
udebug.c
38
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);
|
||||
|
|
Loading…
Reference in a new issue