forked from Minki/linux
Xtensa updates for v5.4:
- add support for xtensa call0 ABI in userspace; - update xtensa virt board DTS for PCI root complex in KIO range; - remove free_initrd_mem. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEK2eFS5jlMn3N6xfYUfnMkfg/oEQFAl2BK9kTHGpjbXZia2Jj QGdtYWlsLmNvbQAKCRBR+cyR+D+gRF8RD/9mNCbX5L4UN9tYwGgDwPoljXx3Gv01 W3ouvCN0RqpK2DHbvPzdTJsN91HF20Gp+STD6HRCNpHJC4PdN8Ie9d6z3wPTBe+k 4BrqzuiuFSjzFC8Fmia1O6WsD3WVYK4FTpkQwxoqZ5NBLx3Ok726/sU5dF9q5asv l05YP0Mj81nGijclYYGLOYYZjjt+JXnaCVX2BO6KN+ECnKwe7l8YskI4SOH7doOM 1nV94Y0mSZsnAQSBsOqcNc15z156i27IPcvuuUR6mtppa77I0UXCez+0N0MZWq6H y4xiqmL/pQ8vijYI7CqSInRunsz6+qzjgGgPIsKwxO7hEkhiC1e8tCGTpAhtqx0E 8VGRWAuS2/9sDc6gKv3ZybHo44/gPKlkIAMrjhubH+9DLEwzP4LEAuL1Mos1fxYH OkMQIB8xOJaOcbUYpGw/cW+a+KB3IbLAdqYHgQZvrKE0tKm6V6Zj9nDSeY1ehwQs FXdQXNL/3lLPhYqsn3SJuQB9LVT980eg1ZonXLTXvgjFg9ConDGj2AOFReS1CUVZ DJf2XEr03rphBGbwt/8glWocq31r/0qVsATHCM0RqOSFH+34X3eENaVCglfiRrU5 IR9Dp6JLZ/8E16u/P90SGdhJ4nIDf9zmN9I9GBifvbpgG3IGsjv4Zkk5hrb50tqm z1cw4ylR4fMS0A== =AYhC -----END PGP SIGNATURE----- Merge tag 'xtensa-20190917' of git://github.com/jcmvbkbc/linux-xtensa Pull Xtensa updates from Max Filippov: - add support for xtensa call0 ABI in userspace - update xtensa virt board DTS for PCI root complex in KIO range - remove free_initrd_mem * tag 'xtensa-20190917' of git://github.com/jcmvbkbc/linux-xtensa: xtensa: virt: move PCI root complex to KIO range xtensa: add support for call0 ABI in userspace xtensa: clean up PS_WOE_BIT usage xtensa: remove free_initrd_mem
This commit is contained in:
commit
6dec8c15e5
@ -385,6 +385,54 @@ config FAST_SYSCALL_SPILL_REGISTERS
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config USER_ABI_CALL0
|
||||
bool
|
||||
|
||||
choice
|
||||
prompt "Userspace ABI"
|
||||
default USER_ABI_DEFAULT
|
||||
help
|
||||
Select supported userspace ABI.
|
||||
|
||||
If unsure, choose the default ABI.
|
||||
|
||||
config USER_ABI_DEFAULT
|
||||
bool "Default ABI only"
|
||||
help
|
||||
Assume default userspace ABI. For XEA2 cores it is windowed ABI.
|
||||
call0 ABI binaries may be run on such kernel, but signal delivery
|
||||
will not work correctly for them.
|
||||
|
||||
config USER_ABI_CALL0_ONLY
|
||||
bool "Call0 ABI only"
|
||||
select USER_ABI_CALL0
|
||||
help
|
||||
Select this option to support only call0 ABI in userspace.
|
||||
Windowed ABI binaries will crash with a segfault caused by
|
||||
an illegal instruction exception on the first 'entry' opcode.
|
||||
|
||||
Choose this option if you're planning to run only user code
|
||||
built with call0 ABI.
|
||||
|
||||
config USER_ABI_CALL0_PROBE
|
||||
bool "Support both windowed and call0 ABI by probing"
|
||||
select USER_ABI_CALL0
|
||||
help
|
||||
Select this option to support both windowed and call0 userspace
|
||||
ABIs. When enabled all processes are started with PS.WOE disabled
|
||||
and a fast user exception handler for an illegal instruction is
|
||||
used to turn on PS.WOE bit on the first 'entry' opcode executed by
|
||||
the userspace.
|
||||
|
||||
This option should be enabled for the kernel that must support
|
||||
both call0 and windowed ABIs in userspace at the same time.
|
||||
|
||||
Note that Xtensa ISA does not guarantee that entry opcode will
|
||||
raise an illegal instruction exception on cores with XEA2 when
|
||||
PS.WOE is disabled, check whether the target core supports it.
|
||||
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
|
||||
config XTENSA_CALIBRATE_CCOUNT
|
||||
|
@ -52,12 +52,12 @@
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <0x1>;
|
||||
|
||||
bus-range = <0x0 0x3f>;
|
||||
reg = <0xc0000000 0x04000000>;
|
||||
bus-range = <0x0 0x3e>;
|
||||
reg = <0xf0100000 0x03f00000>;
|
||||
|
||||
// BUS_ADDRESS(3) CPU_PHYSICAL(1) SIZE(2)
|
||||
ranges = <0x01000000 0x0 0xc4000000 0xc4000000 0x0 0x04000000>,
|
||||
<0x02000000 0x0 0xc8000000 0xc8000000 0x0 0x18000000>;
|
||||
ranges = <0x01000000 0x0 0xf0000000 0xf0000000 0x0 0x00010000>,
|
||||
<0x02000000 0x0 0xf4000000 0xf4000000 0x0 0x08000000>;
|
||||
|
||||
// PCI_DEVICE(3) INT#(1) CONTROLLER(PHANDLE) CONTROLLER_DATA(2)
|
||||
interrupt-map = <
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#define IOADDR(x) (XCHAL_KIO_BYPASS_VADDR + (x))
|
||||
#define IO_SPACE_LIMIT ~0
|
||||
#define PCI_IOBASE ((void __iomem *)XCHAL_KIO_BYPASS_VADDR)
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
|
@ -176,14 +176,21 @@ struct thread_struct {
|
||||
|
||||
/*
|
||||
* Do necessary setup to start up a newly executed thread.
|
||||
* Note: We set-up ps as if we did a call4 to the new pc.
|
||||
* Note: When windowed ABI is used for userspace we set-up ps
|
||||
* as if we did a call4 to the new pc.
|
||||
* set_thread_state in signal.c depends on it.
|
||||
*/
|
||||
#define USER_PS_VALUE ((1 << PS_WOE_BIT) | \
|
||||
#if IS_ENABLED(CONFIG_USER_ABI_CALL0)
|
||||
#define USER_PS_VALUE ((USER_RING << PS_RING_SHIFT) | \
|
||||
(1 << PS_UM_BIT) | \
|
||||
(1 << PS_EXCM_BIT))
|
||||
#else
|
||||
#define USER_PS_VALUE (PS_WOE_MASK | \
|
||||
(1 << PS_CALLINC_SHIFT) | \
|
||||
(USER_RING << PS_RING_SHIFT) | \
|
||||
(1 << PS_UM_BIT) | \
|
||||
(1 << PS_EXCM_BIT))
|
||||
#endif
|
||||
|
||||
/* Clearing a0 terminates the backtrace. */
|
||||
#define start_thread(regs, new_pc, new_sp) \
|
||||
|
@ -81,6 +81,7 @@
|
||||
/* PS register fields. */
|
||||
|
||||
#define PS_WOE_BIT 18
|
||||
#define PS_WOE_MASK 0x00040000
|
||||
#define PS_CALLINC_SHIFT 16
|
||||
#define PS_CALLINC_MASK 0x00030000
|
||||
#define PS_OWB_SHIFT 8
|
||||
|
@ -414,7 +414,7 @@ common_exception:
|
||||
movi a3, LOCKLEVEL
|
||||
|
||||
.Lexception:
|
||||
movi a0, 1 << PS_WOE_BIT
|
||||
movi a0, PS_WOE_MASK
|
||||
or a3, a3, a0
|
||||
#else
|
||||
addi a2, a2, -EXCCAUSE_LEVEL1_INTERRUPT
|
||||
@ -422,7 +422,7 @@ common_exception:
|
||||
extui a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
|
||||
# a3 = PS.INTLEVEL
|
||||
moveqz a3, a0, a2 # a3 = LOCKLEVEL iff interrupt
|
||||
movi a2, 1 << PS_WOE_BIT
|
||||
movi a2, PS_WOE_MASK
|
||||
or a3, a3, a2
|
||||
rsr a2, exccause
|
||||
#endif
|
||||
@ -922,7 +922,7 @@ ENTRY(unrecoverable_exception)
|
||||
wsr a1, windowbase
|
||||
rsync
|
||||
|
||||
movi a1, (1 << PS_WOE_BIT) | LOCKLEVEL
|
||||
movi a1, PS_WOE_MASK | LOCKLEVEL
|
||||
wsr a1, ps
|
||||
rsync
|
||||
|
||||
@ -1003,7 +1003,41 @@ ENTRY(fast_alloca)
|
||||
4: j _WindowUnderflow4
|
||||
ENDPROC(fast_alloca)
|
||||
|
||||
#ifdef CONFIG_USER_ABI_CALL0_PROBE
|
||||
/*
|
||||
* fast illegal instruction handler.
|
||||
*
|
||||
* This is used to fix up user PS.WOE on the exception caused
|
||||
* by the first opcode related to register window. If PS.WOE is
|
||||
* already set it goes directly to the common user exception handler.
|
||||
*
|
||||
* Entry condition:
|
||||
*
|
||||
* a0: trashed, original value saved on stack (PT_AREG0)
|
||||
* a1: a1
|
||||
* a2: new stack pointer, original in DEPC
|
||||
* a3: a3
|
||||
* depc: a2, original value saved on stack (PT_DEPC)
|
||||
* excsave_1: dispatch table
|
||||
*/
|
||||
|
||||
ENTRY(fast_illegal_instruction_user)
|
||||
|
||||
rsr a0, ps
|
||||
bbsi.l a0, PS_WOE_BIT, user_exception
|
||||
s32i a3, a2, PT_AREG3
|
||||
movi a3, PS_WOE_MASK
|
||||
or a0, a0, a3
|
||||
wsr a0, ps
|
||||
l32i a3, a2, PT_AREG3
|
||||
l32i a0, a2, PT_AREG0
|
||||
rsr a2, depc
|
||||
rfe
|
||||
|
||||
ENDPROC(fast_illegal_instruction_user)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* fast system calls.
|
||||
*
|
||||
* WARNING: The kernel doesn't save the entire user context before
|
||||
@ -1359,7 +1393,7 @@ ENTRY(fast_syscall_spill_registers)
|
||||
rsr a3, excsave1
|
||||
l32i a1, a3, EXC_TABLE_KSTK
|
||||
|
||||
movi a4, (1 << PS_WOE_BIT) | LOCKLEVEL
|
||||
movi a4, PS_WOE_MASK | LOCKLEVEL
|
||||
wsr a4, ps
|
||||
rsync
|
||||
|
||||
|
@ -193,7 +193,7 @@ ENTRY(_startup)
|
||||
movi a1, start_info
|
||||
l32i a1, a1, 0
|
||||
|
||||
movi a2, (1 << PS_WOE_BIT) | LOCKLEVEL
|
||||
movi a2, PS_WOE_MASK | LOCKLEVEL
|
||||
# WOE=1, INTLEVEL=LOCKLEVEL, UM=0
|
||||
wsr a2, ps # (enable reg-windows; progmode stack)
|
||||
rsync
|
||||
|
@ -61,7 +61,6 @@ struct screen_info screen_info = {
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
extern unsigned long initrd_start;
|
||||
extern unsigned long initrd_end;
|
||||
int initrd_is_mapped = 0;
|
||||
extern int initrd_below_start_ok;
|
||||
#endif
|
||||
|
||||
@ -332,13 +331,11 @@ void __init setup_arch(char **cmdline_p)
|
||||
/* Reserve some memory regions */
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
if (initrd_start < initrd_end) {
|
||||
initrd_is_mapped = mem_reserve(__pa(initrd_start),
|
||||
__pa(initrd_end)) == 0;
|
||||
if (initrd_start < initrd_end &&
|
||||
!mem_reserve(__pa(initrd_start), __pa(initrd_end)))
|
||||
initrd_below_start_ok = 1;
|
||||
} else {
|
||||
else
|
||||
initrd_start = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
mem_reserve(__pa(_stext), __pa(_end));
|
||||
|
@ -335,7 +335,8 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
||||
{
|
||||
struct rt_sigframe *frame;
|
||||
int err = 0, sig = ksig->sig;
|
||||
unsigned long sp, ra, tp;
|
||||
unsigned long sp, ra, tp, ps;
|
||||
unsigned int base;
|
||||
|
||||
sp = regs->areg[1];
|
||||
|
||||
@ -385,17 +386,26 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
||||
|
||||
/* Set up registers for signal handler; preserve the threadptr */
|
||||
tp = regs->threadptr;
|
||||
ps = regs->ps;
|
||||
start_thread(regs, (unsigned long) ksig->ka.sa.sa_handler,
|
||||
(unsigned long) frame);
|
||||
|
||||
/* Set up a stack frame for a call4
|
||||
* Note: PS.CALLINC is set to one by start_thread
|
||||
*/
|
||||
regs->areg[4] = (((unsigned long) ra) & 0x3fffffff) | 0x40000000;
|
||||
regs->areg[6] = (unsigned long) sig;
|
||||
regs->areg[7] = (unsigned long) &frame->info;
|
||||
regs->areg[8] = (unsigned long) &frame->uc;
|
||||
/* Set up a stack frame for a call4 if userspace uses windowed ABI */
|
||||
if (ps & PS_WOE_MASK) {
|
||||
base = 4;
|
||||
regs->areg[base] =
|
||||
(((unsigned long) ra) & 0x3fffffff) | 0x40000000;
|
||||
ps = (ps & ~(PS_CALLINC_MASK | PS_OWB_MASK)) |
|
||||
(1 << PS_CALLINC_SHIFT);
|
||||
} else {
|
||||
base = 0;
|
||||
regs->areg[base] = (unsigned long) ra;
|
||||
}
|
||||
regs->areg[base + 2] = (unsigned long) sig;
|
||||
regs->areg[base + 3] = (unsigned long) &frame->info;
|
||||
regs->areg[base + 4] = (unsigned long) &frame->uc;
|
||||
regs->threadptr = tp;
|
||||
regs->ps = ps;
|
||||
|
||||
pr_debug("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08lx\n",
|
||||
current->comm, current->pid, sig, frame, regs->pc);
|
||||
|
@ -44,6 +44,11 @@ void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
|
||||
if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
|
||||
return;
|
||||
|
||||
if (IS_ENABLED(CONFIG_USER_ABI_CALL0_ONLY) ||
|
||||
(IS_ENABLED(CONFIG_USER_ABI_CALL0_PROBE) &&
|
||||
!(regs->ps & PS_WOE_MASK)))
|
||||
return;
|
||||
|
||||
/* Two steps:
|
||||
*
|
||||
* 1. Look through the register window for the
|
||||
|
@ -51,6 +51,7 @@
|
||||
extern void kernel_exception(void);
|
||||
extern void user_exception(void);
|
||||
|
||||
extern void fast_illegal_instruction_user(void);
|
||||
extern void fast_syscall_user(void);
|
||||
extern void fast_alloca(void);
|
||||
extern void fast_unaligned(void);
|
||||
@ -87,6 +88,9 @@ typedef struct {
|
||||
|
||||
static dispatch_init_table_t __initdata dispatch_init_table[] = {
|
||||
|
||||
#ifdef CONFIG_USER_ABI_CALL0_PROBE
|
||||
{ EXCCAUSE_ILLEGAL_INSTRUCTION, USER, fast_illegal_instruction_user },
|
||||
#endif
|
||||
{ EXCCAUSE_ILLEGAL_INSTRUCTION, 0, do_illegal_instruction},
|
||||
{ EXCCAUSE_SYSTEM_CALL, USER, fast_syscall_user },
|
||||
{ EXCCAUSE_SYSTEM_CALL, 0, system_call },
|
||||
|
@ -203,16 +203,6 @@ void __init mem_init(void)
|
||||
(unsigned long)(__bss_stop - __bss_start) >> 10);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
extern int initrd_is_mapped;
|
||||
|
||||
void free_initrd_mem(unsigned long start, unsigned long end)
|
||||
{
|
||||
if (initrd_is_mapped)
|
||||
free_reserved_area((void *)start, (void *)end, -1, "initrd");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __init parse_memmap_one(char *p)
|
||||
{
|
||||
char *oldp;
|
||||
|
Loading…
Reference in New Issue
Block a user