Commit 5e3ddf96 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'x86_urgent_for_v5.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Borislav Petkov:
 "The freshest pile of shiny x86 fixes for 5.12:

   - Add the arch-specific mapping between physical and logical CPUs to
     fix devicetree-node lookups

   - Restore the IRQ2 ignore logic

   - Fix get_nr_restart_syscall() to return the correct restart syscall
     number. Split in a 4-patches set to avoid kABI breakage when
     backporting to dead kernels"

* tag 'x86_urgent_for_v5.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/apic/of: Fix CPU devicetree-node lookups
  x86/ioapic: Ignore IRQ2 again
  x86: Introduce restart_block->arch_data to remove TS_COMPAT_RESTART
  x86: Introduce TS_COMPAT_RESTART to fix get_nr_restart_syscall()
  x86: Move TS_COMPAT back to asm/thread_info.h
  kernel, fs: Introduce and use set_restart_fn() and arch_set_restart_data()
parents b35660a7 dd926880
...@@ -551,15 +551,6 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset, ...@@ -551,15 +551,6 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset,
*size = fpu_kernel_xstate_size; *size = fpu_kernel_xstate_size;
} }
/*
* Thread-synchronous status.
*
* This is different from the flags in that nobody else
* ever touches our thread-synchronous status, so we don't
* have to worry about atomic accesses.
*/
#define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/
static inline void static inline void
native_load_sp0(unsigned long sp0) native_load_sp0(unsigned long sp0)
{ {
......
...@@ -205,10 +205,23 @@ static inline int arch_within_stack_frames(const void * const stack, ...@@ -205,10 +205,23 @@ static inline int arch_within_stack_frames(const void * const stack,
#endif #endif
/*
* Thread-synchronous status.
*
* This is different from the flags in that nobody else
* ever touches our thread-synchronous status, so we don't
* have to worry about atomic accesses.
*/
#define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/
#ifndef __ASSEMBLY__
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
#define TS_I386_REGS_POKED 0x0004 /* regs poked by 32-bit ptracer */ #define TS_I386_REGS_POKED 0x0004 /* regs poked by 32-bit ptracer */
#define arch_set_restart_data(restart) \
do { restart->arch_data = current_thread_info()->status; } while (0)
#endif #endif
#ifndef __ASSEMBLY__
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
#define in_ia32_syscall() true #define in_ia32_syscall() true
......
...@@ -2342,6 +2342,11 @@ static int cpuid_to_apicid[] = { ...@@ -2342,6 +2342,11 @@ static int cpuid_to_apicid[] = {
[0 ... NR_CPUS - 1] = -1, [0 ... NR_CPUS - 1] = -1,
}; };
bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
{
return phys_id == cpuid_to_apicid[cpu];
}
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/** /**
* apic_id_is_primary_thread - Check whether APIC ID belongs to a primary thread * apic_id_is_primary_thread - Check whether APIC ID belongs to a primary thread
......
...@@ -1032,6 +1032,16 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin, ...@@ -1032,6 +1032,16 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) { if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) {
irq = mp_irqs[idx].srcbusirq; irq = mp_irqs[idx].srcbusirq;
legacy = mp_is_legacy_irq(irq); legacy = mp_is_legacy_irq(irq);
/*
* IRQ2 is unusable for historical reasons on systems which
* have a legacy PIC. See the comment vs. IRQ2 further down.
*
* If this gets removed at some point then the related code
* in lapic_assign_system_vectors() needs to be adjusted as
* well.
*/
if (legacy && irq == PIC_CASCADE_IR)
return -EINVAL;
} }
mutex_lock(&ioapic_mutex); mutex_lock(&ioapic_mutex);
......
...@@ -766,30 +766,8 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) ...@@ -766,30 +766,8 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)
static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs) static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs)
{ {
/*
* This function is fundamentally broken as currently
* implemented.
*
* The idea is that we want to trigger a call to the
* restart_block() syscall and that we want in_ia32_syscall(),
* in_x32_syscall(), etc. to match whatever they were in the
* syscall being restarted. We assume that the syscall
* instruction at (regs->ip - 2) matches whatever syscall
* instruction we used to enter in the first place.
*
* The problem is that we can get here when ptrace pokes
* syscall-like values into regs even if we're not in a syscall
* at all.
*
* For now, we maintain historical behavior and guess based on
* stored state. We could do better by saving the actual
* syscall arch in restart_block or (with caveats on x32) by
* checking if regs->ip points to 'int $0x80'. The current
* behavior is incorrect if a tracer has a different bitness
* than the tracee.
*/
#ifdef CONFIG_IA32_EMULATION #ifdef CONFIG_IA32_EMULATION
if (current_thread_info()->status & (TS_COMPAT|TS_I386_REGS_POKED)) if (current->restart_block.arch_data & TS_COMPAT)
return __NR_ia32_restart_syscall; return __NR_ia32_restart_syscall;
#endif #endif
#ifdef CONFIG_X86_X32_ABI #ifdef CONFIG_X86_X32_ABI
......
...@@ -1055,10 +1055,9 @@ static long do_restart_poll(struct restart_block *restart_block) ...@@ -1055,10 +1055,9 @@ static long do_restart_poll(struct restart_block *restart_block)
ret = do_sys_poll(ufds, nfds, to); ret = do_sys_poll(ufds, nfds, to);
if (ret == -ERESTARTNOHAND) { if (ret == -ERESTARTNOHAND)
restart_block->fn = do_restart_poll; ret = set_restart_fn(restart_block, do_restart_poll);
ret = -ERESTART_RESTARTBLOCK;
}
return ret; return ret;
} }
...@@ -1080,7 +1079,6 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds, ...@@ -1080,7 +1079,6 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,
struct restart_block *restart_block; struct restart_block *restart_block;
restart_block = &current->restart_block; restart_block = &current->restart_block;
restart_block->fn = do_restart_poll;
restart_block->poll.ufds = ufds; restart_block->poll.ufds = ufds;
restart_block->poll.nfds = nfds; restart_block->poll.nfds = nfds;
...@@ -1091,7 +1089,7 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds, ...@@ -1091,7 +1089,7 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,
} else } else
restart_block->poll.has_timeout = 0; restart_block->poll.has_timeout = 0;
ret = -ERESTART_RESTARTBLOCK; ret = set_restart_fn(restart_block, do_restart_poll);
} }
return ret; return ret;
} }
......
...@@ -23,6 +23,7 @@ enum timespec_type { ...@@ -23,6 +23,7 @@ enum timespec_type {
* System call restart block. * System call restart block.
*/ */
struct restart_block { struct restart_block {
unsigned long arch_data;
long (*fn)(struct restart_block *); long (*fn)(struct restart_block *);
union { union {
/* For futex_wait and futex_wait_requeue_pi */ /* For futex_wait and futex_wait_requeue_pi */
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/restart_block.h> #include <linux/restart_block.h>
#include <linux/errno.h>
#ifdef CONFIG_THREAD_INFO_IN_TASK #ifdef CONFIG_THREAD_INFO_IN_TASK
/* /*
...@@ -59,6 +60,18 @@ enum syscall_work_bit { ...@@ -59,6 +60,18 @@ enum syscall_work_bit {
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifndef arch_set_restart_data
#define arch_set_restart_data(restart) do { } while (0)
#endif
static inline long set_restart_fn(struct restart_block *restart,
long (*fn)(struct restart_block *))
{
restart->fn = fn;
arch_set_restart_data(restart);
return -ERESTART_RESTARTBLOCK;
}
#ifndef THREAD_ALIGN #ifndef THREAD_ALIGN
#define THREAD_ALIGN THREAD_SIZE #define THREAD_ALIGN THREAD_SIZE
#endif #endif
......
...@@ -2728,14 +2728,13 @@ static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val, ...@@ -2728,14 +2728,13 @@ static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,
goto out; goto out;
restart = &current->restart_block; restart = &current->restart_block;
restart->fn = futex_wait_restart;
restart->futex.uaddr = uaddr; restart->futex.uaddr = uaddr;
restart->futex.val = val; restart->futex.val = val;
restart->futex.time = *abs_time; restart->futex.time = *abs_time;
restart->futex.bitset = bitset; restart->futex.bitset = bitset;
restart->futex.flags = flags | FLAGS_HAS_TIMEOUT; restart->futex.flags = flags | FLAGS_HAS_TIMEOUT;
ret = -ERESTART_RESTARTBLOCK; ret = set_restart_fn(restart, futex_wait_restart);
out: out:
if (to) { if (to) {
......
...@@ -854,9 +854,9 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, ...@@ -854,9 +854,9 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
if (flags == TIMER_ABSTIME) if (flags == TIMER_ABSTIME)
return -ERESTARTNOHAND; return -ERESTARTNOHAND;
restart->fn = alarm_timer_nsleep_restart;
restart->nanosleep.clockid = type; restart->nanosleep.clockid = type;
restart->nanosleep.expires = exp; restart->nanosleep.expires = exp;
set_restart_fn(restart, alarm_timer_nsleep_restart);
return ret; return ret;
} }
......
...@@ -1957,9 +1957,9 @@ long hrtimer_nanosleep(ktime_t rqtp, const enum hrtimer_mode mode, ...@@ -1957,9 +1957,9 @@ long hrtimer_nanosleep(ktime_t rqtp, const enum hrtimer_mode mode,
} }
restart = &current->restart_block; restart = &current->restart_block;
restart->fn = hrtimer_nanosleep_restart;
restart->nanosleep.clockid = t.timer.base->clockid; restart->nanosleep.clockid = t.timer.base->clockid;
restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer); restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer);
set_restart_fn(restart, hrtimer_nanosleep_restart);
out: out:
destroy_hrtimer_on_stack(&t.timer); destroy_hrtimer_on_stack(&t.timer);
return ret; return ret;
......
...@@ -1480,8 +1480,8 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags, ...@@ -1480,8 +1480,8 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
if (flags & TIMER_ABSTIME) if (flags & TIMER_ABSTIME)
return -ERESTARTNOHAND; return -ERESTARTNOHAND;
restart_block->fn = posix_cpu_nsleep_restart;
restart_block->nanosleep.clockid = which_clock; restart_block->nanosleep.clockid = which_clock;
set_restart_fn(restart_block, posix_cpu_nsleep_restart);
} }
return error; return error;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment