Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 91e040a7 authored by Vineet Gupta's avatar Vineet Gupta
Browse files

ARC: syscall for userspace cmpxchg assist



Older ARC700 cores (ARC750 specifically) lack instructions to implement
atomic r-w-w. This is problematic for userspace libraries such as NPTL
which need atomic primitives. So enable them by providing kernel assist.
This is costly but really the only sane soluton (othern than tight
spinning using the otherwise availiable atomic exchange EX instruciton).

Good thing is there are only a few of these cores running Linux out in
the wild.

This only works on UP systems.

Reviewed-by: default avatarColin Ian King <colin.king@canonical.com>
Signed-off-by: default avatarVineet Gupta <vgupta@synopsys.com>
parent 1dec7858
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@ int sys_clone_wrapper(int, int, int, int, int);
int sys_cacheflush(uint32_t, uint32_t uint32_t);
int sys_cacheflush(uint32_t, uint32_t uint32_t);
int sys_arc_settls(void *);
int sys_arc_settls(void *);
int sys_arc_gettls(void);
int sys_arc_gettls(void);
int sys_arc_usr_cmpxchg(int *, int, int);


#include <asm-generic/syscalls.h>
#include <asm-generic/syscalls.h>


+5 −4
Original line number Original line Diff line number Diff line
@@ -27,18 +27,19 @@


#define NR_syscalls	__NR_syscalls
#define NR_syscalls	__NR_syscalls


/* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
#define __NR_sysfs		(__NR_arch_specific_syscall + 3)

/* ARC specific syscall */
/* ARC specific syscall */
#define __NR_cacheflush		(__NR_arch_specific_syscall + 0)
#define __NR_cacheflush		(__NR_arch_specific_syscall + 0)
#define __NR_arc_settls		(__NR_arch_specific_syscall + 1)
#define __NR_arc_settls		(__NR_arch_specific_syscall + 1)
#define __NR_arc_gettls		(__NR_arch_specific_syscall + 2)
#define __NR_arc_gettls		(__NR_arch_specific_syscall + 2)
#define __NR_arc_usr_cmpxchg	(__NR_arch_specific_syscall + 4)


__SYSCALL(__NR_cacheflush, sys_cacheflush)
__SYSCALL(__NR_cacheflush, sys_cacheflush)
__SYSCALL(__NR_arc_settls, sys_arc_settls)
__SYSCALL(__NR_arc_settls, sys_arc_settls)
__SYSCALL(__NR_arc_gettls, sys_arc_gettls)
__SYSCALL(__NR_arc_gettls, sys_arc_gettls)

__SYSCALL(__NR_arc_usr_cmpxchg, sys_arc_usr_cmpxchg)

/* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
#define __NR_sysfs		(__NR_arch_specific_syscall + 3)
__SYSCALL(__NR_sysfs, sys_sysfs)
__SYSCALL(__NR_sysfs, sys_sysfs)


#undef __SYSCALL
#undef __SYSCALL
+33 −0
Original line number Original line Diff line number Diff line
@@ -41,6 +41,39 @@ SYSCALL_DEFINE0(arc_gettls)
	return task_thread_info(current)->thr_ptr;
	return task_thread_info(current)->thr_ptr;
}
}


SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new)
{
	int uval;
	int ret;

	/*
	 * This is only for old cores lacking LLOCK/SCOND, which by defintion
	 * can't possibly be SMP. Thus doesn't need to be SMP safe.
	 * And this also helps reduce the overhead for serializing in
	 * the UP case
	 */
	WARN_ON_ONCE(IS_ENABLED(CONFIG_SMP));

	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
		return -EFAULT;

	preempt_disable();

	ret = __get_user(uval, uaddr);
	if (ret)
		goto done;

	if (uval != expected)
		ret = -EAGAIN;
	else
		ret = __put_user(new, uaddr);

done:
	preempt_enable();

	return ret;
}

void arch_cpu_idle(void)
void arch_cpu_idle(void)
{
{
	/* sleep, but enable all interrupts before committing */
	/* sleep, but enable all interrupts before committing */