Failed to read variable with KSEG1 address in MIPS32
06:20 01 Jan 2026

I am working on an embedded RTOS system, where the CPU is a MIPS32.
The GNU ld.script specifies the final binary runs from 0x80000000, I think it is KSEG0 address space.
I wrote a test to read variable by converting its address to KSEG1 region (the MMU in SOC is NOT enabled). But I hit a unexpected result.

Here comes the test codes.

#define to_uncached(p) ((void*)((uintptr_t)(p) | 0x20000000UL))
#define to_cached(p) ((void*)((uintptr_t)(p) & ~0x20000000UL))

#define CACHE_LINE_SIZE 32
#define ALIGN_DOWN(p, a) ((void*)((uintptr_t)(p) & ~((a)-1)))
#define ALIGN_UP(p, a)   ((void*)(((uintptr_t)(p) + (a) - 1) & ~((a)-1)))

static inline void cache_flush(void *addr, size_t len)
{
    void *start = (void*)((uintptr_t)addr & ~31);
    void *end = (void*)((uintptr_t)addr + len + 31 & ~31);

    for (void *p = start; p < end; p = (char*)p + 32) {
        __asm__ volatile ("cache 0x15, 0(%0)" : : "r"(p) : "memory");  // Hit_Writeback_Inv_D
    }
    __asm__ volatile ("sync");
}

static uint32_t intvar = 0x12345678;
static int kseg_test(void)
{
    uint8_t *cached_buf = NULL, *uncached_buf = NULL;

    intvar = 0xabcdef12;
    __asm__ volatile("sync" ::: "memory");

    cached_buf = (uint8_t *)&intvar;
    uncached_buf = to_uncached(cached_buf);

    printf("cached_buf: %p, uncached_buf: %p\n", cached_buf, uncached_buf);
    printf("Initial: cached=%x, uncached=%x\n",
            *(volatile uint32_t*)cached_buf,
            *(volatile uint32_t*)uncached_buf);

    cache_flush(cached_buf, 64);

    printf("After flush: cached=%x, uncached=%x\n",
            *(volatile uint32_t*)cached_buf,
            *(volatile uint32_t*)uncached_buf);
    return 0;
}

And the result is,

cached_buf: 0x804578d0, uncached_buf: 0xa04578d0
Initial: cached=abcdef12, uncached=12345678
After flush: cached=abcdef12, uncached=12345678

After calling cache_flush, reading the memory with KSEG1 address got the stale data!!!

I ran the RTOS command md to read memory by specifying the KSEG0 and KSEG1 addresses, I got the expected data, as follows,

# md 0x804578d0 1
0x804578d0: abcdef12

# md 0xa04578d0 1
0xa04578d0: abcdef12

The md is using _printf(" %08x", *(unsigned int *)addr); to read memory from address specified.

So what is wrong with my kseg_test, why it did NOT read the memory correctly, but md command can do it ??

c caching mips mips32