From 79c8aa4da3d5453dd956d2170d1c9c716311ea06 Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Thu, 13 Aug 2026 04:40:26 +0200 Subject: [PATCH 01/17] microblaze: Fix MB_MANAGER build with older binutils Commit 88707ebe77e2 ("microblaze: Add custom break vector handler for mb manager") added the suspend mnemonic to the MB Manager break handler. GNU as only learned this mnemonic in binutils 2.42. Linux supports binutils 2.30, where enabling CONFIG_MB_MANAGER fails: arch/microblaze/kernel/entry.S:946: Error: unknown opcode "suspend" The suspend mnemonic is an alias for mbar 24, and both encode as 0xbb020004. Use the underlying instruction, which GNU as 2.30 already supports. Fixes: 88707ebe77e2 ("microblaze: Add custom break vector handler for mb manager") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202310310151.UhB396Qs-lkp@intel.com/ Suggested-by: Michal Simek Cc: stable@vger.kernel.org Assisted-by: Codex:gpt-5.6-sol Signed-off-by: Karl Mehltretter Link: https://patch.msgid.link/20260813024026.5402-1-kmehltretter@gmail.com Signed-off-by: Michal Simek --- arch/microblaze/kernel/entry.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 582d7256d815..ad44341a5dbc 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -943,7 +943,7 @@ ret_from_break: mbar 1 mbar 2 bri 4 - suspend + mbar 24 /* suspend */ nop #endif From e44c5ef7a05c5cfc996be1aafedfdee3edd96c4c Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 1 Aug 2026 21:09:48 +0200 Subject: [PATCH 02/17] microblaze: drop unneeded semicolon When a function-like macro expands to an expression, that expression doesn't need a semicolon after it. All uses have been verified to have their own semicolons. This was found using the following Coccinelle semantic patch: @r@ identifier i : script:ocaml() { String.lowercase_ascii i = i }; expression e; @@ *#define i(...) e; Signed-off-by: Julia Lawall Link: https://patch.msgid.link/20260801191002.1383835-2-Julia.Lawall@inria.fr Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c | 2 +- arch/microblaze/kernel/cpu/cpuinfo-static.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c index c7ee51b0900e..1cc3fd9846ad 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c @@ -23,7 +23,7 @@ #define CI(c, p) { ci->c = PVR_##p(pvr); } #define err_printk(x) \ - pr_err("ERROR: Microblaze " x "-different for PVR and DTS\n"); + pr_err("ERROR: Microblaze " x "-different for PVR and DTS\n") void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) { diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c index 03da36dc6d9c..1e4d30b6cb01 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-static.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c @@ -18,7 +18,7 @@ static const char family_string[] = CONFIG_XILINX_MICROBLAZE0_FAMILY; static const char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER; #define err_printk(x) \ - pr_err("ERROR: Microblaze " x "-different for kernel and DTS\n"); + pr_err("ERROR: Microblaze " x "-different for kernel and DTS\n") void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu) { From 730e01d932496f7bd536fc185d3aab6646dea0f4 Mon Sep 17 00:00:00 2001 From: Ramin Moussavi Date: Fri, 21 Aug 2026 17:18:05 +0200 Subject: [PATCH 03/17] microblaze: wire up sigaltstack sigaltstack is wired to sys_ni_syscall - microblaze is the only architecture without it - although the microblaze signal delivery code fully supports the alternate signal stack: get_sigframe() picks the stack via sigsp(), setup_rt_frame() saves it with __save_altstack() and sys_rt_sigreturn() calls restore_altstack(). Wire it up to sys_sigaltstack. Tested on qemu petalogix-s3adsp1800 (microblazeel) with the uClibc-ng test suite: the five sigaltstack-dependent NPTL tests (tst-cancel20/21, tst-cancelx20/21, tst-signal6) pass; before this change sigaltstack() returned ENOSYS. Assisted-by: Claude:claude-opus-5 Signed-off-by: Ramin Moussavi Tested-by: Waldemar Brodkorb Link: https://patch.msgid.link/20260821151809.1233057-2-ramin.moussavi@yacoub.de Signed-off-by: Michal Simek --- arch/microblaze/kernel/syscalls/syscall.tbl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl index c55a5c96f49b..76d7cbe2a133 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -193,7 +193,7 @@ 183 common getcwd sys_getcwd 184 common capget sys_capget 185 common capset sys_capset -186 common sigaltstack sys_ni_syscall +186 common sigaltstack sys_sigaltstack 187 common sendfile sys_sendfile 188 common getpmsg sys_ni_syscall 189 common putpmsg sys_ni_syscall From c5947d28c20955de897eeb98430f96db0494f7d7 Mon Sep 17 00:00:00 2001 From: Ramin Moussavi Date: Fri, 21 Aug 2026 17:18:06 +0200 Subject: [PATCH 04/17] microblaze: reserve the ABI argument-home area in the signal frame The MicroBlaze procedure call standard reserves [r1+0] for the return address and lets a callee store its incoming register arguments r5..r10 into the caller-provided home slots at [r1+4]..[r1+24]. When the kernel enters a signal handler it sets r1 to point at struct rt_sigframe, whose leading member is the siginfo prepared for the handler. A handler that homes its arguments - which an unoptimised (-O0) build always does - therefore overwrites the first 24 bytes of that siginfo, so an SA_SIGINFO handler reads corrupted values. The stores stay within siginfo (128 bytes) and do not reach the ucontext behind it. Reserve the home area by making a seven-word gap -- the return-address slot plus the six argument slots, 28 bytes -- the first member of struct rt_sigframe, so the handler's argument stores land in scratch space instead of clobbering siginfo. Tested on qemu-system-microblazeel (petalogix-s3adsp1800) with the uClibc-ng NPTL test suite: tst-timer4, tst-timer5, tst-mqueue5 and tst-signal6 pass; before this change they failed because the handler clobbered the signal frame. Fixes: 2148daa9c45f ("microblaze_v8: Signal support") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-5 Signed-off-by: Ramin Moussavi Tested-by: Waldemar Brodkorb Link: https://patch.msgid.link/20260821151809.1233057-3-ramin.moussavi@yacoub.de Signed-off-by: Michal Simek --- arch/microblaze/kernel/signal.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index c78a0ff48066..4956014a9937 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -49,6 +49,14 @@ struct sigframe { }; struct rt_sigframe { + /* + * Home area for the handler's register arguments: the MicroBlaze + * ABI reserves [r1+0] for the return address and lets the callee + * store r5..r10 at [r1+4]..[r1+24], and r1 points at this frame + * when the handler is entered. Without the gap those stores + * corrupt frame->info. + */ + unsigned long abi_gap[7]; struct siginfo info; struct ucontext uc; unsigned long tramp[2]; /* signal trampoline */ From da6829138a39fa3b9ec318ca54ff89af9d94d350 Mon Sep 17 00:00:00 2001 From: Ramin Moussavi Date: Fri, 21 Aug 2026 17:18:07 +0200 Subject: [PATCH 05/17] microblaze: don't clobber r3/r4 restored by rt_sigreturn ret_from_trap begins by storing the system call return values r3 and r4 back into the saved user pt_regs. That is right for an ordinary system call, but sys_rt_sigreturn() returns through the same path and has to be transparent: restore_sigcontext() has just filled pt_regs from the signal frame, and every register must reach userspace exactly as saved. The two stores overwrite the restored r3/r4 with whatever the C function left in those registers. Only r4 is actually lost, and that follows from how sigreturn is written everywhere rather than from chance. Architectures have sys_rt_sigreturn() return the restored return-value register precisely so that this writeback stores the restored value -- arm returns regs->ARM_r0, riscv and csky regs->a0, arc regs->r0 -- and microblaze does the same through *rval_p = regs->r3 in restore_sigcontext(). But the entry macros treat r3 and r4 as a pair, so ret_from_trap writes back two registers while a C function has only one return value; nothing carries the restored r4. Commit 791d0a169b91 ("microblaze: Fix sys_rt_sigreturn_wrapper") introduced this in v2.6.37. The old wrapper saved r3/r4 before the call and reloaded them from pt_regs afterwards; switching brlid to brid removed the only point where they were reloaded, and the stores have been overwriting them ever since. Fix it the way the sibling paths already behave: ret_from_irq and ret_from_exc restore the full register set and do not perform these stores at all. Label the instruction after the stores ret_from_trap_no_rval and enter there, biasing r15 by -8 so that the ABI return "rtsd r15, 8" lands on it; naming the entry rather than computing ret_from_trap + 8 keeps it correct if the number of stores ever changes. Restoring the old save/reload would work too, but costs four memory accesses and a branch to undo damage that is better not done. Any value the compiler keeps in r4 across a signal is lost. The tightest windows are the lwx/swx compare-and-swap retry loops gcc emits for atomics: in uClibc-ng's libc.so alone, 50 of 364 such loops hold the address in r4. This is not specific to one libc -- musl passes the address as "r"(p), and glibc has no microblaze atomic-machine.h and so uses gcc's __atomic builtins, which expand the same way. Triggering it needs threads plus a signal storm, which is why it survived 15 years. Reproduced on qemu-system-microblazeel (petalogix-s3adsp1800) by running the uClibc-ng NPTL test tst-eintr1 40 times against an unchanged userspace: on v7.2 built with gcc 16.2.0, 23 of 40 iterations died with SIGSEGV without this patch and 0 of 40 with it; on v7.0 built with gcc 12.5.0 the same comparison gave 6 of 40 against 0 of 40. The register dump of a failing iteration shows the signature: a zero r4 and a fault at address 0, while r3 came back intact. Fixes: 791d0a169b91 ("microblaze: Fix sys_rt_sigreturn_wrapper") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-5 Signed-off-by: Ramin Moussavi Tested-by: Waldemar Brodkorb Link: https://patch.msgid.link/20260821151809.1233057-4-ramin.moussavi@yacoub.de Signed-off-by: Michal Simek --- arch/microblaze/kernel/entry.S | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index ad44341a5dbc..efa4ab056fb5 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -434,7 +434,13 @@ C_ENTRY(_user_exception): C_ENTRY(ret_from_trap): swi r3, r1, PT_R3 swi r4, r1, PT_R4 - +/* + * Entry point for returns that must not store r3/r4 back into pt_regs, + * i.e. rt_sigreturn, which has already restored them from the signal + * context. Reached as "rtsd r15, 8" with r15 set to this label minus 8, + * so it stays correct if the number of stores above ever changes. + */ +ret_from_trap_no_rval: lwi r11, r1, PT_MODE; /* See if returning to kernel mode, if so, skip resched &c. */ bnei r11, 2f; @@ -518,6 +524,15 @@ C_ENTRY(ret_from_kernel_thread): C_ENTRY(sys_rt_sigreturn_wrapper): addik r30, r0, 0 /* no restarts */ + /* + * rt_sigreturn restores the full register set from the signal + * context, so it must skip the r3/r4 syscall-return stores at the + * head of ret_from_trap which would otherwise overwrite the + * just-restored r3/r4. Every C function returns with "rtsd r15, 8" + * -- the ABI return, where the 8 skips the caller's branch and its + * delay slot -- so bias r15 by -8 to land on ret_from_trap_no_rval. + */ + addik r15, r0, ret_from_trap_no_rval - 8 brid sys_rt_sigreturn /* Do real work */ addik r5, r1, 0; /* add user context as 1st arg */ From c35d40a3efd2e575ef51a761e983f2bf7113be6c Mon Sep 17 00:00:00 2001 From: Ramin Moussavi Date: Fri, 21 Aug 2026 17:18:08 +0200 Subject: [PATCH 06/17] microblaze: restore the ABI argument home area below pt_regs (PTO) The MicroBlaze ABI has the caller reserve stack space for the arguments it passes in registers: REG_PARM_STACK_SPACE is 24 and OUTGOING_REG_PARM_STACK_SPACE is 1 in the gcc backend, so a callee may write to [caller_sp + 4, caller_sp + 28). The kernel calls C functions from entry.S with r1 pointing at pt_regs, handing the callee license to spill its incoming arguments over the saved registers -- the syscall dispatch is the worst case, where the first argument slot is PT_R1, the saved user stack pointer. This was latent until GCC 15: since 3b9b8d6cfdf5 ("ira: Scale save/restore costs of callee save registers with block frequency") the allocator prefers spilling incoming arguments over copying them into callee-saved registers, and a kernel built with gcc >= 15 (without the TARGET_CALLEE_SAVE_COST workaround some distributions carry) corrupts PT_R1 on the first syscall: init takes SIGSEGV and the kernel panics. The kernel had exactly this reservation until 2011: commit 6e83557c38b4 ("microblaze: Remove r0_ram pointer and PTO alignment") removed STATE_SAVE_ARG_SPACE and with it the PTO offset, as part of cleaning up what was thought to be copied-from-v850 leftovers. Restore it: the frame is STATE_SAVE_SIZE = PT_SIZE + PTO, r1 stays at the frame base through every asm-to-C call, and the saved registers are reached at r1 + PTO + PT_*. PTO is 28 rather than the historic 24, which was one word short: FIRST_PARM_OFFSET is 4 and REG_PARM_STACK_SPACE is 24, so the area spans [sp+4, sp+28) and needs 28 bytes. With 24 the last argument slot overlapped pt_regs' r0 -- harmless only because r0 is the constant-zero register. STACK_BOUNDARY is 32 bits, so 28 needs no further rounding. Two places deliberately keep their mainline addressing. hw_exception_handler.S needs no offset change: its real-mode handler saves into the standalone pt_pool_space buffer rather than a stack frame, and _unaligned_data_exception works through a pointer to pt_regs in r7, where plain PT_* offsets are already right. And the user-SP reload after popping the frame keeps PT_R1 - PT_SIZE because PTO cancels there: (PTO + PT_R1) - (PT_SIZE + PTO) = PT_R1 - PT_SIZE. Both are exactly as the pre-2011 code had them. The instruction count is unchanged -- the same instructions with different immediates, no per-call reservation and no trampolines. The cost is 28 bytes more kernel stack per saved frame. Fixes: 6e83557c38b4 ("microblaze: Remove r0_ram pointer and PTO alignment") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-5 Signed-off-by: Ramin Moussavi Tested-by: Waldemar Brodkorb Link: https://patch.msgid.link/20260821151809.1233057-5-ramin.moussavi@yacoub.de Signed-off-by: Michal Simek --- arch/microblaze/include/asm/entry.h | 13 + arch/microblaze/include/asm/processor.h | 2 +- arch/microblaze/kernel/entry.S | 329 +++++++++--------- arch/microblaze/kernel/hw_exception_handler.S | 5 + arch/microblaze/kernel/process.c | 5 +- 5 files changed, 189 insertions(+), 165 deletions(-) diff --git a/arch/microblaze/include/asm/entry.h b/arch/microblaze/include/asm/entry.h index 9efadf12397c..05acf4d7bc4b 100644 --- a/arch/microblaze/include/asm/entry.h +++ b/arch/microblaze/include/asm/entry.h @@ -21,6 +21,19 @@ #define PER_CPU(var) var +/* + * The MicroBlaze ABI has the caller reserve an argument home area: + * REG_PARM_STACK_SPACE is 24 and OUTGOING_REG_PARM_STACK_SPACE is 1, so a + * callee may write to [caller_sp + 4, caller_sp + 28). The kernel calls C + * with r1 at the frame base, so reserve that area below pt_regs and reach + * the saved registers through PTO. This restores what 6e83557c38b4 + * ("microblaze: Remove r0_ram pointer and PTO alignment") removed; the old + * value of 24 was one word short and left the last argument slot + * overlapping pt_regs' r0. + */ +#define PTO 28 +#define STATE_SAVE_SIZE (PT_SIZE + PTO) + # ifndef __ASSEMBLER__ DECLARE_PER_CPU(unsigned int, KSP); /* Saved kernel stack pointer */ DECLARE_PER_CPU(unsigned int, KM); /* Kernel/user mode */ diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h index d59bdfffca7c..595c24db2728 100644 --- a/arch/microblaze/include/asm/processor.h +++ b/arch/microblaze/include/asm/processor.h @@ -73,7 +73,7 @@ unsigned long __get_wchan(struct task_struct *p); # define task_regs(task) ((struct pt_regs *)task_tos(task) - 1) # define task_pt_regs_plus_args(tsk) \ - ((void *)task_pt_regs(tsk)) + (((void *)task_pt_regs(tsk)) - PTO) # define task_sp(task) (task_regs(task)->r1) # define task_pc(task) (task_regs(task)->pc) diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index efa4ab056fb5..ebc8bcb98c52 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -177,78 +177,78 @@ syscall_debug_table: 1: #define SAVE_REGS \ - swi r2, r1, PT_R2; /* Save SDA */ \ - swi r3, r1, PT_R3; \ - swi r4, r1, PT_R4; \ - swi r5, r1, PT_R5; \ - swi r6, r1, PT_R6; \ - swi r7, r1, PT_R7; \ - swi r8, r1, PT_R8; \ - swi r9, r1, PT_R9; \ - swi r10, r1, PT_R10; \ - swi r11, r1, PT_R11; /* save clobbered regs after rval */\ - swi r12, r1, PT_R12; \ - swi r13, r1, PT_R13; /* Save SDA2 */ \ - swi r14, r1, PT_PC; /* PC, before IRQ/trap */ \ - swi r15, r1, PT_R15; /* Save LP */ \ - swi r16, r1, PT_R16; \ - swi r17, r1, PT_R17; \ - swi r18, r1, PT_R18; /* Save asm scratch reg */ \ - swi r19, r1, PT_R19; \ - swi r20, r1, PT_R20; \ - swi r21, r1, PT_R21; \ - swi r22, r1, PT_R22; \ - swi r23, r1, PT_R23; \ - swi r24, r1, PT_R24; \ - swi r25, r1, PT_R25; \ - swi r26, r1, PT_R26; \ - swi r27, r1, PT_R27; \ - swi r28, r1, PT_R28; \ - swi r29, r1, PT_R29; \ - swi r30, r1, PT_R30; \ - swi r31, r1, PT_R31; /* Save current task reg */ \ + swi r2, r1, PTO+PT_R2; /* Save SDA */ \ + swi r3, r1, PTO+PT_R3; \ + swi r4, r1, PTO+PT_R4; \ + swi r5, r1, PTO+PT_R5; \ + swi r6, r1, PTO+PT_R6; \ + swi r7, r1, PTO+PT_R7; \ + swi r8, r1, PTO+PT_R8; \ + swi r9, r1, PTO+PT_R9; \ + swi r10, r1, PTO+PT_R10; \ + swi r11, r1, PTO+PT_R11; /* save clobbered regs after rval */\ + swi r12, r1, PTO+PT_R12; \ + swi r13, r1, PTO+PT_R13; /* Save SDA2 */ \ + swi r14, r1, PTO+PT_PC; /* PC, before IRQ/trap */ \ + swi r15, r1, PTO+PT_R15; /* Save LP */ \ + swi r16, r1, PTO+PT_R16; \ + swi r17, r1, PTO+PT_R17; \ + swi r18, r1, PTO+PT_R18; /* Save asm scratch reg */ \ + swi r19, r1, PTO+PT_R19; \ + swi r20, r1, PTO+PT_R20; \ + swi r21, r1, PTO+PT_R21; \ + swi r22, r1, PTO+PT_R22; \ + swi r23, r1, PTO+PT_R23; \ + swi r24, r1, PTO+PT_R24; \ + swi r25, r1, PTO+PT_R25; \ + swi r26, r1, PTO+PT_R26; \ + swi r27, r1, PTO+PT_R27; \ + swi r28, r1, PTO+PT_R28; \ + swi r29, r1, PTO+PT_R29; \ + swi r30, r1, PTO+PT_R30; \ + swi r31, r1, PTO+PT_R31; /* Save current task reg */ \ mfs r11, rmsr; /* save MSR */ \ - swi r11, r1, PT_MSR; + swi r11, r1, PTO+PT_MSR; #define RESTORE_REGS_GP \ - lwi r2, r1, PT_R2; /* restore SDA */ \ - lwi r3, r1, PT_R3; \ - lwi r4, r1, PT_R4; \ - lwi r5, r1, PT_R5; \ - lwi r6, r1, PT_R6; \ - lwi r7, r1, PT_R7; \ - lwi r8, r1, PT_R8; \ - lwi r9, r1, PT_R9; \ - lwi r10, r1, PT_R10; \ - lwi r11, r1, PT_R11; /* restore clobbered regs after rval */\ - lwi r12, r1, PT_R12; \ - lwi r13, r1, PT_R13; /* restore SDA2 */ \ - lwi r14, r1, PT_PC; /* RESTORE_LINK PC, before IRQ/trap */\ - lwi r15, r1, PT_R15; /* restore LP */ \ - lwi r16, r1, PT_R16; \ - lwi r17, r1, PT_R17; \ - lwi r18, r1, PT_R18; /* restore asm scratch reg */ \ - lwi r19, r1, PT_R19; \ - lwi r20, r1, PT_R20; \ - lwi r21, r1, PT_R21; \ - lwi r22, r1, PT_R22; \ - lwi r23, r1, PT_R23; \ - lwi r24, r1, PT_R24; \ - lwi r25, r1, PT_R25; \ - lwi r26, r1, PT_R26; \ - lwi r27, r1, PT_R27; \ - lwi r28, r1, PT_R28; \ - lwi r29, r1, PT_R29; \ - lwi r30, r1, PT_R30; \ - lwi r31, r1, PT_R31; /* Restore cur task reg */ + lwi r2, r1, PTO+PT_R2; /* restore SDA */ \ + lwi r3, r1, PTO+PT_R3; \ + lwi r4, r1, PTO+PT_R4; \ + lwi r5, r1, PTO+PT_R5; \ + lwi r6, r1, PTO+PT_R6; \ + lwi r7, r1, PTO+PT_R7; \ + lwi r8, r1, PTO+PT_R8; \ + lwi r9, r1, PTO+PT_R9; \ + lwi r10, r1, PTO+PT_R10; \ + lwi r11, r1, PTO+PT_R11; /* restore clobbered regs after rval */\ + lwi r12, r1, PTO+PT_R12; \ + lwi r13, r1, PTO+PT_R13; /* restore SDA2 */ \ + lwi r14, r1, PTO+PT_PC; /* RESTORE_LINK PC, before IRQ/trap */\ + lwi r15, r1, PTO+PT_R15; /* restore LP */ \ + lwi r16, r1, PTO+PT_R16; \ + lwi r17, r1, PTO+PT_R17; \ + lwi r18, r1, PTO+PT_R18; /* restore asm scratch reg */ \ + lwi r19, r1, PTO+PT_R19; \ + lwi r20, r1, PTO+PT_R20; \ + lwi r21, r1, PTO+PT_R21; \ + lwi r22, r1, PTO+PT_R22; \ + lwi r23, r1, PTO+PT_R23; \ + lwi r24, r1, PTO+PT_R24; \ + lwi r25, r1, PTO+PT_R25; \ + lwi r26, r1, PTO+PT_R26; \ + lwi r27, r1, PTO+PT_R27; \ + lwi r28, r1, PTO+PT_R28; \ + lwi r29, r1, PTO+PT_R29; \ + lwi r30, r1, PTO+PT_R30; \ + lwi r31, r1, PTO+PT_R31; /* Restore cur task reg */ #define RESTORE_REGS \ - lwi r11, r1, PT_MSR; \ + lwi r11, r1, PTO+PT_MSR; \ mts rmsr , r11; \ RESTORE_REGS_GP #define RESTORE_REGS_RTBD \ - lwi r11, r1, PT_MSR; \ + lwi r11, r1, PTO+PT_MSR; \ andni r11, r11, MSR_EIP; /* clear EIP */ \ ori r11, r11, MSR_EE | MSR_BIP; /* set EE and BIP */ \ mts rmsr , r11; \ @@ -265,11 +265,11 @@ syscall_debug_table: lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); \ /* FIXME: I can add these two lines to one */ \ /* tophys(r1,r1); */ \ - /* addik r1, r1, -PT_SIZE; */ \ - addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; \ + /* addik r1, r1, -STATE_SAVE_SIZE; */ \ + addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \ SAVE_REGS \ brid 2f; \ - swi r1, r1, PT_MODE; \ + swi r1, r1, PTO+PT_MODE; \ 1: /* User-mode state save. */ \ lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\ tophys(r1,r1); \ @@ -277,12 +277,13 @@ syscall_debug_table: /* MS these three instructions can be added to one */ \ /* addik r1, r1, THREAD_SIZE; */ \ /* tophys(r1,r1); */ \ - /* addik r1, r1, -PT_SIZE; */ \ - addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; \ + /* addik r1, r1, -STATE_SAVE_SIZE; */ \ + addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR \ + - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \ SAVE_REGS \ lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); \ - swi r11, r1, PT_R1; /* Store user SP. */ \ - swi r0, r1, PT_MODE; /* Was in user-mode. */ \ + swi r11, r1, PTO+PT_R1; /* Store user SP. */ \ + swi r0, r1, PTO+PT_MODE; /* Was in user-mode. */ \ /* MS: I am clearing UMS even in case when I come from kernel space */ \ clear_ums; \ 2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); @@ -292,7 +293,7 @@ syscall_debug_table: .extern cpuinfo C_ENTRY(mb_flush_dcache): - addik r1, r1, -PT_SIZE + addik r1, r1, -STATE_SAVE_SIZE SAVE_REGS addik r3, r0, cpuinfo @@ -305,12 +306,12 @@ C_ENTRY(mb_flush_dcache): addk r9, r9, r8 RESTORE_REGS - addik r1, r1, PT_SIZE + addik r1, r1, STATE_SAVE_SIZE rtsd r15, 8 nop C_ENTRY(mb_invalidate_icache): - addik r1, r1, -PT_SIZE + addik r1, r1, -STATE_SAVE_SIZE SAVE_REGS addik r3, r0, cpuinfo @@ -323,7 +324,7 @@ C_ENTRY(mb_invalidate_icache): addk r9, r9, r8 RESTORE_REGS - addik r1, r1, PT_SIZE + addik r1, r1, STATE_SAVE_SIZE rtsd r15, 8 nop @@ -350,18 +351,18 @@ C_ENTRY(_user_exception): addik r1, r1, THREAD_SIZE; tophys(r1,r1); - addik r1, r1, -PT_SIZE; /* Make room on the stack. */ + addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ SAVE_REGS - swi r0, r1, PT_R3 - swi r0, r1, PT_R4 + swi r0, r1, PTO+PT_R3 + swi r0, r1, PTO+PT_R4 - swi r0, r1, PT_MODE; /* Was in user-mode. */ + swi r0, r1, PTO+PT_MODE; /* Was in user-mode. */ lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); - swi r11, r1, PT_R1; /* Store user SP. */ + swi r11, r1, PTO+PT_R1; /* Store user SP. */ clear_ums; 2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* Save away the syscall number. */ - swi r12, r1, PT_R0; + swi r12, r1, PTO+PT_R0; tovirt(r1,r1) /* where the trap should return need -8 to adjust for rtsd r15, 8*/ @@ -380,18 +381,18 @@ C_ENTRY(_user_exception): beqi r11, 4f addik r3, r0, -ENOSYS - swi r3, r1, PT_R3 + swi r3, r1, PTO+PT_R3 brlid r15, do_syscall_trace_enter - addik r5, r1, PT_R0 + addik r5, r1, PTO+PT_R0 # do_syscall_trace_enter returns the new syscall nr. addk r12, r0, r3 - lwi r5, r1, PT_R5; - lwi r6, r1, PT_R6; - lwi r7, r1, PT_R7; - lwi r8, r1, PT_R8; - lwi r9, r1, PT_R9; - lwi r10, r1, PT_R10; + lwi r5, r1, PTO+PT_R5; + lwi r6, r1, PTO+PT_R6; + lwi r7, r1, PTO+PT_R7; + lwi r8, r1, PTO+PT_R8; + lwi r9, r1, PTO+PT_R9; + lwi r10, r1, PTO+PT_R10; 4: /* Jump to the appropriate function for the system call number in r12 * (r12 is not preserved), or return an error if r12 is not valid. @@ -432,8 +433,8 @@ C_ENTRY(_user_exception): /* Entry point used to return from a syscall/trap */ /* We re-enable BIP bit before state restore */ C_ENTRY(ret_from_trap): - swi r3, r1, PT_R3 - swi r4, r1, PT_R4 + swi r3, r1, PTO+PT_R3 + swi r4, r1, PTO+PT_R4 /* * Entry point for returns that must not store r3/r4 back into pt_regs, * i.e. rt_sigreturn, which has already restored them from the signal @@ -441,7 +442,7 @@ C_ENTRY(ret_from_trap): * so it stays correct if the number of stores above ever changes. */ ret_from_trap_no_rval: - lwi r11, r1, PT_MODE; + lwi r11, r1, PTO+PT_MODE; /* See if returning to kernel mode, if so, skip resched &c. */ bnei r11, 2f; /* We're returning to user mode, so check for various conditions that @@ -453,7 +454,7 @@ ret_from_trap_no_rval: beqi r11, 1f brlid r15, do_syscall_trace_leave - addik r5, r1, PT_R0 + addik r5, r1, PTO+PT_R0 1: /* We're returning to user mode, so check for various conditions that * trigger rescheduling. */ @@ -472,7 +473,7 @@ ret_from_trap_no_rval: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; beqi r11, 4f; /* Signals to handle, handle them */ - addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ + addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ bralid r15, do_notify_resume; /* Handle any signals */ add r6, r30, r0; /* Arg 2: int in_syscall */ add r30, r0, r0 /* no more restarts */ @@ -484,7 +485,11 @@ ret_from_trap_no_rval: VM_OFF; tophys(r1,r1); RESTORE_REGS_RTBD; - addik r1, r1, PT_SIZE /* Clean up stack space. */ + addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ + /* + * Deliberately PT_SIZE, not STATE_SAVE_SIZE: r1 is back at the stack + * top, so PTO cancels and the saved SP sits at PT_R1 - PT_SIZE. + */ lwi r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */ bri 6f; @@ -493,7 +498,7 @@ ret_from_trap_no_rval: VM_OFF; tophys(r1,r1); RESTORE_REGS_RTBD; - addik r1, r1, PT_SIZE /* Clean up stack space. */ + addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ tovirt(r1,r1); 6: TRAP_return: /* Make global symbol for debugging */ @@ -534,7 +539,7 @@ C_ENTRY(sys_rt_sigreturn_wrapper): */ addik r15, r0, ret_from_trap_no_rval - 8 brid sys_rt_sigreturn /* Do real work */ - addik r5, r1, 0; /* add user context as 1st arg */ + addik r5, r1, PTO; /* add user context as 1st arg */ /* * HW EXCEPTION rutine start @@ -545,7 +550,7 @@ C_ENTRY(full_exception_trap): addik r17, r17, -4 SAVE_STATE /* Save registers */ /* PC, before IRQ/trap - this is one instruction above */ - swi r17, r1, PT_PC; + swi r17, r1, PTO+PT_PC; tovirt(r1,r1) /* FIXME this can be store directly in PT_ESR reg. * I tested it but there is a fault */ @@ -555,7 +560,7 @@ C_ENTRY(full_exception_trap): mfs r7, rfsr; /* save FSR */ mts rfsr, r0; /* Clear sticky fsr */ rted r0, full_exception - addik r5, r1, 0 /* parameter struct pt_regs * regs */ + addik r5, r1, PTO /* parameter struct pt_regs * regs */ /* * Unaligned data trap. @@ -581,14 +586,14 @@ C_ENTRY(unaligned_data_trap): lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); SAVE_STATE /* Save registers.*/ /* PC, before IRQ/trap - this is one instruction above */ - swi r17, r1, PT_PC; + swi r17, r1, PTO+PT_PC; tovirt(r1,r1) /* where the trap should return need -8 to adjust for rtsd r15, 8 */ addik r15, r0, ret_from_exc-8 mfs r3, resr /* ESR */ mfs r4, rear /* EAR */ rtbd r0, _unaligned_data_exception - addik r7, r1, 0 /* parameter struct pt_regs * regs */ + addik r7, r1, PTO /* parameter struct pt_regs * regs */ /* * Page fault traps. @@ -611,30 +616,30 @@ C_ENTRY(unaligned_data_trap): C_ENTRY(page_fault_data_trap): SAVE_STATE /* Save registers.*/ /* PC, before IRQ/trap - this is one instruction above */ - swi r17, r1, PT_PC; + swi r17, r1, PTO+PT_PC; tovirt(r1,r1) /* where the trap should return need -8 to adjust for rtsd r15, 8 */ addik r15, r0, ret_from_exc-8 mfs r6, rear /* parameter unsigned long address */ mfs r7, resr /* parameter unsigned long error_code */ rted r0, do_page_fault - addik r5, r1, 0 /* parameter struct pt_regs * regs */ + addik r5, r1, PTO /* parameter struct pt_regs * regs */ C_ENTRY(page_fault_instr_trap): SAVE_STATE /* Save registers.*/ /* PC, before IRQ/trap - this is one instruction above */ - swi r17, r1, PT_PC; + swi r17, r1, PTO+PT_PC; tovirt(r1,r1) /* where the trap should return need -8 to adjust for rtsd r15, 8 */ addik r15, r0, ret_from_exc-8 mfs r6, rear /* parameter unsigned long address */ ori r7, r0, 0 /* parameter unsigned long error_code */ rted r0, do_page_fault - addik r5, r1, 0 /* parameter struct pt_regs * regs */ + addik r5, r1, PTO /* parameter struct pt_regs * regs */ /* Entry point used to return from an exception. */ C_ENTRY(ret_from_exc): - lwi r11, r1, PT_MODE; + lwi r11, r1, PTO+PT_MODE; bnei r11, 2f; /* See if returning to kernel mode, */ /* ... if so, skip resched &c. */ @@ -666,7 +671,7 @@ C_ENTRY(ret_from_exc): * complete register state. Here we save anything not saved by * the normal entry sequence, so that it may be safely restored * (in a possibly modified form) after do_notify_resume returns. */ - addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ + addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ bralid r15, do_notify_resume; /* Handle any signals */ addi r6, r0, 0; /* Arg 2: int in_syscall */ bri 1b @@ -678,7 +683,7 @@ C_ENTRY(ret_from_exc): tophys(r1,r1); RESTORE_REGS_RTBD; - addik r1, r1, PT_SIZE /* Clean up stack space. */ + addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */ bri 6f; @@ -687,7 +692,7 @@ C_ENTRY(ret_from_exc): VM_OFF; tophys(r1,r1); RESTORE_REGS_RTBD; - addik r1, r1, PT_SIZE /* Clean up stack space. */ + addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ tovirt(r1,r1); 6: @@ -720,10 +725,10 @@ C_ENTRY(_interrupt): tophys(r1,r1); /* MS: I have in r1 physical address where stack is */ /* save registers */ /* MS: Make room on the stack -> activation record */ - addik r1, r1, -PT_SIZE; + addik r1, r1, -STATE_SAVE_SIZE; SAVE_REGS brid 2f; - swi r1, r1, PT_MODE; /* 0 - user mode, 1 - kernel mode */ + swi r1, r1, PTO+PT_MODE; /* 0 - user mode, 1 - kernel mode */ 1: /* User-mode state save. */ /* MS: get the saved current */ @@ -733,23 +738,23 @@ C_ENTRY(_interrupt): addik r1, r1, THREAD_SIZE; tophys(r1,r1); /* save registers */ - addik r1, r1, -PT_SIZE; + addik r1, r1, -STATE_SAVE_SIZE; SAVE_REGS /* calculate mode */ - swi r0, r1, PT_MODE; + swi r0, r1, PTO+PT_MODE; lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); - swi r11, r1, PT_R1; + swi r11, r1, PTO+PT_R1; clear_ums; 2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); tovirt(r1,r1) addik r15, r0, irq_call; irq_call:rtbd r0, do_IRQ; - addik r5, r1, 0; + addik r5, r1, PTO; /* MS: we are in virtual mode */ ret_from_irq: - lwi r11, r1, PT_MODE; + lwi r11, r1, PTO+PT_MODE; bnei r11, 2f; 1: @@ -765,7 +770,7 @@ ret_from_irq: 5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; beqid r11, no_intr_resched /* Handle a signal return; Pending signals should be in r18. */ - addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ + addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ bralid r15, do_notify_resume; /* Handle any signals */ addi r6, r0, 0; /* Arg 2: int in_syscall */ bri 1b @@ -778,7 +783,7 @@ no_intr_resched: VM_OFF; tophys(r1,r1); RESTORE_REGS - addik r1, r1, PT_SIZE /* MS: Clean up stack space. */ + addik r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */ lwi r1, r1, PT_R1 - PT_SIZE; bri 6f; /* MS: Return to kernel state. */ @@ -801,7 +806,7 @@ restore: VM_OFF /* MS: turn off MMU */ tophys(r1,r1) RESTORE_REGS - addik r1, r1, PT_SIZE /* MS: Clean up stack space. */ + addik r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */ tovirt(r1,r1); 6: IRQ_return: /* MS: Make global symbol for debugging */ @@ -820,29 +825,29 @@ C_ENTRY(_xtmr_manager_reset): lwi r1, r0, xmb_manager_stackpointer /* Restore MSR */ - lwi r2, r1, PT_MSR + lwi r2, r1, PTO+PT_MSR mts rmsr, r2 bri 4 /* restore Special purpose registers */ - lwi r2, r1, PT_PID + lwi r2, r1, PTO+PT_PID mts rpid, r2 - lwi r2, r1, PT_TLBI + lwi r2, r1, PTO+PT_TLBI mts rtlbx, r2 - lwi r2, r1, PT_ZPR + lwi r2, r1, PTO+PT_ZPR mts rzpr, r2 #if CONFIG_XILINX_MICROBLAZE0_USE_FPU - lwi r2, r1, PT_FSR + lwi r2, r1, PTO+PT_FSR mts rfsr, r2 #endif /* restore all the tlb's */ addik r3, r0, TOPHYS(tlb_skip) - addik r6, r0, PT_TLBL0 - addik r7, r0, PT_TLBH0 + addik r6, r0, PTO+PT_TLBL0 + addik r7, r0, PTO+PT_TLBH0 restore_tlb: add r6, r6, r1 add r7, r7, r1 @@ -868,9 +873,9 @@ ret_from_reset: VM_OFF /* MS: Restore all regs */ RESTORE_REGS - lwi r14, r1, PT_R14 - lwi r16, r1, PT_PC - addik r1, r1, PT_SIZE + 36 + lwi r14, r1, PTO+PT_R14 + lwi r16, r1, PTO+PT_PC + addik r1, r1, STATE_SAVE_SIZE + 36 rtbd r16, 0 nop @@ -885,11 +890,11 @@ C_ENTRY(_xmb_manager_break): * Reserve memory in the stack for context store/restore * (which includes memory for storing tlbs (max two tlbs)) */ - addik r1, r1, -PT_SIZE - 36 + addik r1, r1, -STATE_SAVE_SIZE - 36 swi r1, r0, xmb_manager_stackpointer SAVE_REGS - swi r14, r1, PT_R14 /* rewrite saved R14 value */ - swi r16, r1, PT_PC; /* PC and r16 are the same */ + swi r14, r1, PTO+PT_R14 /* rewrite saved R14 value */ + swi r16, r1, PTO+PT_PC; /* PC and r16 are the same */ lwi r6, r0, TOPHYS(xmb_manager_baseaddr) lwi r7, r0, TOPHYS(xmb_manager_crval) @@ -903,25 +908,25 @@ C_ENTRY(_xmb_manager_break): /* Save the special purpose registers */ mfs r2, rpid - swi r2, r1, PT_PID + swi r2, r1, PTO+PT_PID mfs r2, rtlbx - swi r2, r1, PT_TLBI + swi r2, r1, PTO+PT_TLBI mfs r2, rzpr - swi r2, r1, PT_ZPR + swi r2, r1, PTO+PT_ZPR #if CONFIG_XILINX_MICROBLAZE0_USE_FPU mfs r2, rfsr - swi r2, r1, PT_FSR + swi r2, r1, PTO+PT_FSR #endif mfs r2, rmsr - swi r2, r1, PT_MSR + swi r2, r1, PTO+PT_MSR /* Save all the tlb's */ addik r3, r0, TOPHYS(tlb_skip) - addik r6, r0, PT_TLBL0 - addik r7, r0, PT_TLBH0 + addik r6, r0, PTO+PT_TLBL0 + addik r7, r0, PTO+PT_TLBH0 save_tlb: add r6, r6, r1 add r7, r7, r1 @@ -978,28 +983,28 @@ C_ENTRY(_debug_exception): lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ /* BIP bit is set on entry, no interrupts can occur */ - addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; + addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; SAVE_REGS; /* save all regs to pt_reg structure */ - swi r0, r1, PT_R0; /* R0 must be saved too */ - swi r14, r1, PT_R14 /* rewrite saved R14 value */ - swi r16, r1, PT_PC; /* PC and r16 are the same */ + swi r0, r1, PTO+PT_R0; /* R0 must be saved too */ + swi r14, r1, PTO+PT_R14 /* rewrite saved R14 value */ + swi r16, r1, PTO+PT_PC; /* PC and r16 are the same */ /* save special purpose registers to pt_regs */ mfs r11, rear; - swi r11, r1, PT_EAR; + swi r11, r1, PTO+PT_EAR; mfs r11, resr; - swi r11, r1, PT_ESR; + swi r11, r1, PTO+PT_ESR; mfs r11, rfsr; - swi r11, r1, PT_FSR; + swi r11, r1, PTO+PT_FSR; /* stack pointer is in physical address at it is decrease - * by PT_SIZE but we need to get correct R1 value */ - addik r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + PT_SIZE; - swi r11, r1, PT_R1 + * by STATE_SAVE_SIZE but we need to get correct R1 value */ + addik r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + STATE_SAVE_SIZE; + swi r11, r1, PTO+PT_R1 /* MS: r31 - current pointer isn't changed */ tovirt(r1,r1) #ifdef CONFIG_KGDB - addi r5, r1, 0 /* pass pt_reg address as the first arg */ + addi r5, r1, PTO /* pass pt_reg address as the first arg */ addik r15, r0, dbtrap_call; /* return address */ rtbd r0, microblaze_kgdb_break nop; @@ -1015,16 +1020,16 @@ C_ENTRY(_debug_exception): addik r1, r1, THREAD_SIZE; /* calculate kernel stack pointer */ tophys(r1,r1); - addik r1, r1, -PT_SIZE; /* Make room on the stack. */ + addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ SAVE_REGS; - swi r16, r1, PT_PC; /* Save LP */ - swi r0, r1, PT_MODE; /* Was in user-mode. */ + swi r16, r1, PTO+PT_PC; /* Save LP */ + swi r0, r1, PTO+PT_MODE; /* Was in user-mode. */ lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); - swi r11, r1, PT_R1; /* Store user SP. */ + swi r11, r1, PTO+PT_R1; /* Store user SP. */ lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); tovirt(r1,r1) set_vms; - addik r5, r1, 0; + addik r5, r1, PTO; addik r15, r0, dbtrap_call; dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */ rtbd r0, sw_exception @@ -1032,7 +1037,7 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */ /* MS: The first instruction for the second part of the gdb/kgdb */ set_bip; /* Ints masked for state restore */ - lwi r11, r1, PT_MODE; + lwi r11, r1, PTO+PT_MODE; bnei r11, 2f; /* MS: Return to user space - gdb */ 1: @@ -1051,7 +1056,7 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */ 5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; beqi r11, 4f; /* Signals to handle, handle them */ - addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ + addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ bralid r15, do_notify_resume; /* Handle any signals */ addi r6, r0, 0; /* Arg 2: int in_syscall */ bri 1b @@ -1062,7 +1067,7 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */ tophys(r1,r1); /* MS: Restore all regs */ RESTORE_REGS_RTBD - addik r1, r1, PT_SIZE /* Clean up stack space */ + addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space */ lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */ DBTRAP_return_user: /* MS: Make global symbol for debugging */ rtbd r16, 0; /* MS: Instructions to return from a debug trap */ @@ -1073,9 +1078,9 @@ DBTRAP_return_user: /* MS: Make global symbol for debugging */ tophys(r1,r1); /* MS: Restore all regs */ RESTORE_REGS_RTBD - lwi r14, r1, PT_R14; - lwi r16, r1, PT_PC; - addik r1, r1, PT_SIZE; /* MS: Clean up stack space */ + lwi r14, r1, PTO+PT_R14; + lwi r16, r1, PTO+PT_PC; + addik r1, r1, STATE_SAVE_SIZE; /* MS: Clean up stack space */ tovirt(r1,r1); DBTRAP_return_kernel: /* MS: Make global symbol for debugging */ rtbd r16, 0; /* MS: Instructions to return from a debug trap */ @@ -1173,7 +1178,7 @@ ENTRY(_switch_to) .ent xmb_inject_err .type xmb_inject_err, @function xmb_inject_err: - addik r1, r1, -PT_SIZE + addik r1, r1, -STATE_SAVE_SIZE SAVE_REGS /* Switch to real mode */ @@ -1197,7 +1202,7 @@ xmb_inject_err: nop; 1: RESTORE_REGS - addik r1, r1, PT_SIZE + addik r1, r1, STATE_SAVE_SIZE rtsd r15, 8; nop; .end xmb_inject_err diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S index 07ea23965f81..4693916be526 100644 --- a/arch/microblaze/kernel/hw_exception_handler.S +++ b/arch/microblaze/kernel/hw_exception_handler.S @@ -313,6 +313,11 @@ _MB_HW_ExceptionVectorTable: .align 4 .ent _hw_exception_handler _hw_exception_handler: + /* + * This handler saves into the static pt_pool_space buffer, not into a + * stack frame, so the plain PT_* offsets are right here -- do not add + * the PTO of entry.S's frames. + */ swi r1, r0, TOPHYS(pt_pool_space + PT_R1); /* GET_SP */ /* Save date to kernel memory. Here is the problem * when you came from user space */ diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index 6cbf642d7b80..090e1697ea7a 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -19,6 +19,7 @@ #include #include #include +#include void show_regs(struct pt_regs *regs) { @@ -65,7 +66,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) * the registers. That's OK for a brand new thread.*/ memset(childregs, 0, sizeof(struct pt_regs)); memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); - ti->cpu_context.r1 = (unsigned long)childregs; + ti->cpu_context.r1 = (unsigned long)childregs - PTO; ti->cpu_context.r20 = (unsigned long)args->fn; ti->cpu_context.r19 = (unsigned long)args->fn_arg; childregs->pt_mode = 1; @@ -79,7 +80,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) childregs->r1 = usp; memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); - ti->cpu_context.r1 = (unsigned long)childregs; + ti->cpu_context.r1 = (unsigned long)childregs - PTO; childregs->msr |= MSR_UMS; /* we should consider the fact that childregs is a copy of the parent From ca35dd21a5f8343f47a23e4e5b3f0ffccf76a4ae Mon Sep 17 00:00:00 2001 From: Sam Price Date: Fri, 21 Aug 2026 17:18:09 +0200 Subject: [PATCH 07/17] microblaze: preserve the MSR carry flags across signals setup_sigcontext() and restore_sigcontext() copy r0-r31, pc, ear, esr and fsr to and from the signal frame but never touch MSR. The interrupted MSR is therefore dropped from the signal context entirely: the handler's ucontext does not expose it, a handler cannot adjust the resumed arithmetic flags through uc_mcontext.regs.msr, and -- because restore_sigcontext() leaves regs->msr as whatever the rt_sigreturn trap left in it -- the interrupted context resumes with the carry produced by the syscall entry path (_user_exception does "addi r14, r14, 4", which writes carry), not with its own. Other architectures round-trip the user-visible flags through the signal frame (arm's cpsr, csky's carry, x86's eflags), so a handler can both read and adjust the resumed flags; purely privileged status registers such as riscv's sstatus are left out. MicroBlaze should do the same for the user-writable bits. Concretely, MSR[C] (carry) is lost across signal delivery. Code that keeps a live carry across a point where a signal can be delivered -- for example an lwx/swx compare-and-swap retry loop, between the swx and the carry test -- resumes with the handler's carry and mis-evaluates the result; the same failure class as the rt_sigreturn r3/r4 clobber, reached through a different register. Demonstrated under qemu-system-microblazeel (machine petalogix-s3adsp1800): a handler that sets MSR_C in uc_mcontext.regs.msr has no effect before this change (0 of 132 in-window signals propagated) and takes effect after (130 of 132). Save MSR in setup_sigcontext() so the handler's ucontext exposes it. The signal frame is user-writable, so restore_sigcontext() must not restore it verbatim: MicroBlaze packs the user-writable carry (MSR_C, MSR_CC) and the privileged control bits (MSR_UM, MSR_VM, MSR_IE, MSR_EE, ...) into the one register, and a verbatim restore would let userspace alter privileged return state -- rtbd derives the resumed mode from MSR_UMS/MSR_VMS. Restore only MSR_C | MSR_CC from the frame and keep the rest from the current regs->msr. This mirrors x86's restore_sigcontext(), which masks the restored EFLAGS to FIX_EFLAGS for the same reason; arches whose status register is purely privileged (e.g. riscv sstatus) simply do not restore it at all. Comment on the exposed MSR reworded: it is not read-only, restore_sigcontext() applies MSR_C|MSR_CC from the frame. Author's Signed-off-by kept; he agreed to comment and changelog cleanups. Fixes: 2148daa9c45f ("microblaze_v8: Signal support") Cc: stable@vger.kernel.org Signed-off-by: Sam Price Signed-off-by: Ramin Moussavi Tested-by: Waldemar Brodkorb Link: https://patch.msgid.link/20260821151809.1233057-6-ramin.moussavi@yacoub.de Signed-off-by: Michal Simek --- arch/microblaze/kernel/signal.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 4956014a9937..6bbc16f98d5e 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -81,6 +82,22 @@ static int restore_sigcontext(struct pt_regs *regs, COPY(pc); COPY(ear); COPY(esr); COPY(fsr); #undef COPY + /* + * The frame is user-writable, so restore only the user-writable + * status flags (carry) and keep the kernel-controlled MSR bits + * (UMS/VMS/IE/EE/...) from regs->msr: rtbd derives the resumed mode + * from UMS/VMS, so a verbatim restore would hand userspace the + * privileged return state. Same idea as x86 masking the restored + * EFLAGS to FIX_EFLAGS. + */ + { + unsigned long msr; + + err |= __get_user(msr, &sc->regs.msr); + regs->msr = (regs->msr & ~(MSR_C | MSR_CC)) | + (msr & (MSR_C | MSR_CC)); + } + *rval_p = regs->r3; return err; @@ -140,6 +157,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, COPY(r26); COPY(r27); COPY(r28); COPY(r29); COPY(r30); COPY(r31); COPY(pc); COPY(ear); COPY(esr); COPY(fsr); + COPY(msr); /* restore_sigcontext() accepts only carry state */ #undef COPY err |= __put_user(mask, &sc->oldmask); From aeedf85beac51c7cd8f7bf4c918a0104dfdb8b78 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 26 May 2026 20:40:59 +0200 Subject: [PATCH 08/17] microblaze: CCF: fix refcount leak Every value returned from of_clk_get() is supposed to be cleaned up via clk_put() once not needed anymore. Fixes: c1120542b99a ("microblaze: Add support for CCF") Signed-off-by: Alexander A. Klimov Link: https://patch.msgid.link/20260526184105.18962-4-grandmaster@al2klimov.de Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cpuinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index cd9b4450763b..32c508e85408 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -133,6 +133,7 @@ void __init setup_cpuinfo_clk(void) cpuinfo.cpu_clock_freq = fcpu(cpu, "timebase-frequency"); } else { cpuinfo.cpu_clock_freq = clk_get_rate(clk); + clk_put(clk); } if (!cpuinfo.cpu_clock_freq) { From 8518fd17ccef4a7d77877ccb0403b722106ad1a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Jean?= Date: Fri, 21 Aug 2026 10:30:27 +0000 Subject: [PATCH 09/17] microblaze: prevent ptrace writes to MSR and pt_mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit arch_ptrace() accepts PTRACE_POKEUSR for every aligned offset below PT_SIZE. This includes the saved machine status register and pt_mode, which are kernel-owned execution state rather than general registers. On return from an exception, rtbd copies MSR_UMS to the live MSR_UM bit. An unprivileged same-UID tracer can therefore clear MSR_UMS in its tracee's saved register frame and make the tracee resume in supervisor mode. pt_mode also controls whether later entry paths classify the frame as kernel or user state. Reject PTRACE_POKEUSR writes to both fields while retaining read access. Fixes: 2b4384542691 ("microblaze_v8: ptrace support") Assisted-by: Codex:gpt-5 Signed-off-by: Jérémy Jean Link: https://patch.msgid.link/20260821103026.3627292-2-Jeremy.Jean@oss.cyber.gouv.fr Signed-off-by: Michal Simek --- arch/microblaze/kernel/ptrace.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c index 236264e932d6..ac1f0503216b 100644 --- a/arch/microblaze/kernel/ptrace.c +++ b/arch/microblaze/kernel/ptrace.c @@ -101,6 +101,9 @@ long arch_ptrace(struct task_struct *child, long request, } else { rval = -EIO; } + } else if (request == PTRACE_POKEUSR && + (addr == PT_MSR || addr == PT_MODE)) { + rval = -EIO; } else if (addr < PT_SIZE && (addr & 0x3) == 0) { microblaze_reg_t *reg_addr = reg_save_addr(addr, child); if (request == PTRACE_PEEKUSR) From 5ac0aed54f94f936ef4a8709c90a4b56c7b12c63 Mon Sep 17 00:00:00 2001 From: Hemanth Selam Date: Fri, 4 Sep 2026 17:03:54 +0530 Subject: [PATCH 10/17] microblaze: fix typo "multipler" in comment Correct "multipler" to "multiplier", reported by scripts/checkpatch.pl using the misspelling list in scripts/spelling.txt. Only touches comments, no code changes. Assisted-by: Cursor:claude-opus-5 Signed-off-by: Hemanth Selam Signed-off-by: Michal Simek --- arch/microblaze/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile index 02e6be9c5b0d..56a161147606 100644 --- a/arch/microblaze/Makefile +++ b/arch/microblaze/Makefile @@ -16,7 +16,7 @@ export CPU_VER CPU_MAJOR CPU_MINOR CPU_REV # The various CONFIG_XILINX cpu features options are integers 0/1/2... # rather than bools y/n -# Work out HW multipler support. This is tricky. +# Work out HW multiplier support. This is tricky. # 1. Spartan2 has no HW multipliers. # 2. MicroBlaze v3.x always uses them, except in Spartan 2 # 3. All other FPGa/CPU ver combos, we can trust the CONFIG_ settings From 54c35131e628e1a18f02365495a24a73a1fb515e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Mon, 14 Sep 2026 01:50:08 +0200 Subject: [PATCH 11/17] microblaze: uaccess: Zero out destination on failed get_user() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On failure get_user() is supposed to zero out the destination variable. This is documented in the kdoc of the microblaze get_user() implementation and validated in lib/tests/usercopy_kunit.c. Currently that zeroing is missing. Add it. Fixes: 0d6de9532663 ("microblaze_mmu_v2: uaccess MMU update") Signed-off-by: Thomas Weißschuh Reviewed-by: David Gow Link: https://patch.msgid.link/20260914-kunit-microblaze-v2-1-7d5756e858f8@weissschuh.net Signed-off-by: Michal Simek --- arch/microblaze/include/asm/uaccess.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index afa0dd8d013f..77203af255e5 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h @@ -95,7 +95,8 @@ extern long __user_bad(void); #define get_user(x, ptr) ({ \ const typeof(*(ptr)) __user *__gu_ptr = (ptr); \ access_ok(__gu_ptr, sizeof(*__gu_ptr)) ? \ - __get_user(x, __gu_ptr) : -EFAULT; \ + __get_user(x, __gu_ptr) : \ + ((x) = 0, -EFAULT); \ }) #define __get_user(x, ptr) \ From b9eababe8c0b9f71ce7f35f903879a7fcb6daebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Mon, 14 Sep 2026 01:50:09 +0200 Subject: [PATCH 12/17] microblaze: Pass -m{big,little}-endian through KBUILD_CPPFLAGS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These parameters are also necessary for preprocessed files which do not contain code. One example is arch/microblaze/kernel/vmlinux.lds.S which inspects __MICROBLAZEEL__ for the definition of 'jiffies_64'. As currently the endianness is not passed from the build system for this file, the preprocessor will instead use the default endianness of the toolchain. When a default big-endian toolchain is used to build a little-endian kernel, that kernel will hang during delay calibration as 'jiffies' never changes. Make sure all preprocessor invocations know about the correct endianness by passing it through KBUILD_CPPFLAGS. This will also be inherited by CFLAGS and AFLAGS. Fixes: 02b08045a030 ("microblaze: Add support for little-endian Microblaze") Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20260914-kunit-microblaze-v2-2-7d5756e858f8@weissschuh.net Signed-off-by: Michal Simek --- arch/microblaze/Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile index 56a161147606..01085dd5e6f8 100644 --- a/arch/microblaze/Makefile +++ b/arch/microblaze/Makefile @@ -34,12 +34,10 @@ CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_BARREL) += -mxl-barrel-shift CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR) += -mxl-pattern-compare ifdef CONFIG_CPU_BIG_ENDIAN -KBUILD_CFLAGS += -mbig-endian -KBUILD_AFLAGS += -mbig-endian +KBUILD_CPPFLAGS += -mbig-endian KBUILD_LDFLAGS += -EB else -KBUILD_CFLAGS += -mlittle-endian -KBUILD_AFLAGS += -mlittle-endian +KBUILD_CPPFLAGS += -mlittle-endian KBUILD_LDFLAGS += -EL endif From 4ebcbacb0b0adf827cd9475f36f866deda39cbfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Mon, 14 Sep 2026 01:50:10 +0200 Subject: [PATCH 13/17] microblaze: reset: Call POWER_OFF handlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit System power off might be implemented through sys_off handlers. Currently these are not respected on microblaze. On power_off call into the generic power off function which will execute all regustered handlers. Signed-off-by: Thomas Weißschuh Acked-by: David Gow Link: https://patch.msgid.link/20260914-kunit-microblaze-v2-3-7d5756e858f8@weissschuh.net Signed-off-by: Michal Simek --- arch/microblaze/kernel/reset.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c index 2f66c7963084..774bc1f79119 100644 --- a/arch/microblaze/kernel/reset.c +++ b/arch/microblaze/kernel/reset.c @@ -28,6 +28,7 @@ void machine_halt(void) void machine_power_off(void) { pr_notice("Machine power off...\n"); + do_kernel_power_off(); while (1) ; } From 7d376ea6a7f9518929b0621aa06c4bd348374098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Mon, 14 Sep 2026 01:50:11 +0200 Subject: [PATCH 14/17] microblaze: reset: Provide a power off handler through an unaligned PC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit microblaze is missing a generic architecture-wide power off mechanism. To enable KUnit for microblaze it is necessary for KUnit to shut down the machine in a way that QEMU will recognize. The machines emulated by QEMU do not provide machine-specific power off functionality which could be used. However at least the petalogix-s3adsp1800 machine will abort if an unaligned instruction is executed. An ugly message will be printed but that is not an issue for KUnit. Make use of this to provide a power off handler. Signed-off-by: Thomas Weißschuh Tested-by: David Gow Link: https://patch.msgid.link/20260914-kunit-microblaze-v2-4-7d5756e858f8@weissschuh.net Signed-off-by: Michal Simek --- arch/microblaze/Kconfig | 9 +++++++++ arch/microblaze/kernel/reset.c | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 484ebb3baedf..0ca8999dd770 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -216,3 +216,12 @@ config MB_MANAGER Say N here unless you know what you are doing. endmenu + +config MB_POWER_OFF_THROUGH_UNALIGNED_PC + bool "Power off through unaligned PC" + help + This options adds a power off handler which executes an unaligned PC + so the machine resets in a generic way. This works for the + petalogix-s3adsp1800 QEMU machine. + + Say N here unless you know what you are doing. diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c index 774bc1f79119..42031c535d48 100644 --- a/arch/microblaze/kernel/reset.c +++ b/arch/microblaze/kernel/reset.c @@ -41,3 +41,24 @@ void machine_restart(char *cmd) pr_emerg("Reboot failed -- System halted\n"); while (1); } + +#ifdef CONFIG_MB_POWER_OFF_THROUGH_UNALIGNED_PC +static int unaligned_pc_sys_off(struct sys_off_data *data) +{ + __asm__( + "bri 1\n" + ); + + return NOTIFY_DONE; +} + +static int __init register_unaligned_pc_sys_off(void) +{ + struct sys_off_handler *sys_off; + + sys_off = register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_LOW, + unaligned_pc_sys_off, NULL); + return PTR_ERR_OR_ZERO(sys_off); +} +device_initcall(register_unaligned_pc_sys_off); +#endif /* CONFIG_MB_POWER_OFF_THROUGH_UNALIGNED_PC */ From 98f468b04d5cc3be5382a923f19ab289e0c40fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Mon, 14 Sep 2026 01:50:12 +0200 Subject: [PATCH 15/17] kunit: qemu_configs: Add microblaze configurations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add basic configurations to run kunit tests on big and little endian microblaze. Suggested-by: Michal Simek Signed-off-by: Thomas Weißschuh Reviewed-by: David Gow Link: https://patch.msgid.link/20260914-kunit-microblaze-v2-5-7d5756e858f8@weissschuh.net Signed-off-by: Michal Simek --- .../kunit/qemu_configs/microblazebe.py | 24 +++++++++++++++++ .../kunit/qemu_configs/microblazeel.py | 27 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 tools/testing/kunit/qemu_configs/microblazebe.py create mode 100644 tools/testing/kunit/qemu_configs/microblazeel.py diff --git a/tools/testing/kunit/qemu_configs/microblazebe.py b/tools/testing/kunit/qemu_configs/microblazebe.py new file mode 100644 index 000000000000..f37b7af20142 --- /dev/null +++ b/tools/testing/kunit/qemu_configs/microblazebe.py @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-only +from ..qemu_config import QemuArchParams + +QEMU_ARCH = QemuArchParams(linux_arch='microblaze', + kconfig=''' +CONFIG_KERNEL_BASE_ADDR=0x90000000 +CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 +CONFIG_XILINX_MICROBLAZE0_USE_DIV=0 +CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=1 +CONFIG_XILINX_MICROBLAZE0_USE_FPU=0 +CONFIG_CPU_BIG_ENDIAN=y +CONFIG_SERIAL_UARTLITE=y +CONFIG_SERIAL_UARTLITE_CONSOLE=y +CONFIG_MB_POWER_OFF_THROUGH_UNALIGNED_PC=y +''', + qemu_arch='microblaze', + kernel_path='arch/microblaze/boot/linux.bin', + kernel_command_line='kunit_shutdown=poweroff', + extra_qemu_params=[ + '-M', 'petalogix-s3adsp1800', + ], +) diff --git a/tools/testing/kunit/qemu_configs/microblazeel.py b/tools/testing/kunit/qemu_configs/microblazeel.py new file mode 100644 index 000000000000..a8bc572d892a --- /dev/null +++ b/tools/testing/kunit/qemu_configs/microblazeel.py @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-only +from ..qemu_config import QemuArchParams + +QEMU_ARCH = QemuArchParams(linux_arch='microblaze', + kconfig=''' +CONFIG_KERNEL_BASE_ADDR=0x50000000 +CONFIG_XILINX_MICROBLAZE0_FAMILY="virtex5" +CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 +CONFIG_XILINX_MICROBLAZE0_USE_DIV=1 +CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=2 +CONFIG_XILINX_MICROBLAZE0_USE_FPU=1 +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_16550A_VARIANTS=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_MB_POWER_OFF_THROUGH_UNALIGNED_PC=y +''', + qemu_arch='microblaze', + kernel_path='arch/microblaze/boot/linux.bin', + kernel_command_line='kunit_shutdown=poweroff', + extra_qemu_params=[ + '-M', 'petalogix-ml605', + ], +) From 6b125c73aaa0dab9ce625437c63b176afe453776 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 14 Sep 2026 12:22:35 +0200 Subject: [PATCH 16/17] microblaze: Enable xilinx dmas and axi emac drivers Both drivers are used on Microblaze systems for quite a long time that's why enable them. Link: https://patch.msgid.link/6d41613ed4ccfdc38ec47070b79a5893e3abc2a6.1789381354.git.michal.simek@amd.com Signed-off-by: Michal Simek --- arch/microblaze/configs/mmu_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/microblaze/configs/mmu_defconfig b/arch/microblaze/configs/mmu_defconfig index fbbdcb394ca2..7f9b19d0d9db 100644 --- a/arch/microblaze/configs/mmu_defconfig +++ b/arch/microblaze/configs/mmu_defconfig @@ -70,6 +70,8 @@ CONFIG_XILINX_WATCHDOG=y CONFIG_FB=y CONFIG_FB_XILINX=y # CONFIG_USB_SUPPORT is not set +CONFIG_DMADEVICES=y +CONFIG_XILINX_DMA=y CONFIG_UIO=y CONFIG_UIO_PDRV_GENIRQ=y CONFIG_UIO_DMEM_GENIRQ=y From d037d22b216b52cc7c45c4b7ec06f3929d5a03f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sat, 19 Sep 2026 20:43:24 +0200 Subject: [PATCH 17/17] microblaze: Build userprogs for the correct endianness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently microblaze userprogs are built for whichever endianness is the default for the used toolchain. They may not be the correct one for the actually built kernel. Implement the correct hooks to build userprogs so they can run on the built kernel. Also test the endianness in CC_CAN_LINK. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20260919-microblaze-cc-can-link-v1-1-01da67e75ebb@weissschuh.net Signed-off-by: Michal Simek --- arch/microblaze/Kconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 0ca8999dd770..9063a91cfb41 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -3,6 +3,7 @@ config MICROBLAZE def_bool y select ARCH_32BIT_OFF_T select ARCH_NO_SWAP + select ARCH_HAS_CC_CAN_LINK select ARCH_HAS_DMA_PREP_COHERENT select ARCH_HAS_GCOV_PROFILE_ALL select ARCH_HAS_SYNC_DMA_FOR_CPU @@ -225,3 +226,13 @@ config MB_POWER_OFF_THROUGH_UNALIGNED_PC petalogix-s3adsp1800 QEMU machine. Say N here unless you know what you are doing. + +config ARCH_CC_CAN_LINK + bool + default $(cc_can_link_user,-mlittle-endian) if CPU_LITTLE_ENDIAN + default $(cc_can_link_user,-mbig-endian) if CPU_BIG_ENDIAN + +config ARCH_USERFLAGS + string + default "-mlittle-endian" if CPU_LITTLE_ENDIAN + default "-mbig-endian" if CPU_BIG_ENDIAN