um: Remove broken SMP support

At times where UML used the TT mode to operate it had
kind of SMP support. It never got finished nor was
stable.
Let's rip out that cruft and stop confusing developers
which do tree-wide SMP cleanups.

If someone wants SMP support UML it has do be done from scratch.

Signed-off-by: Richard Weinberger <richard@nod.at>
This commit is contained in:
Richard Weinberger 2015-03-18 21:42:54 +01:00
parent d0b5e15f0c
commit 28fa468f53
10 changed files with 2 additions and 366 deletions

View file

@ -95,36 +95,6 @@ config MAGIC_SYSRQ
The keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
unless you really know what this hack does.
config SMP
bool "Symmetric multi-processing support"
default n
depends on BROKEN
help
This option enables UML SMP support.
It is NOT related to having a real SMP box. Not directly, at least.
UML implements virtual SMP by allowing as many processes to run
simultaneously on the host as there are virtual processors configured.
Obviously, if the host is a uniprocessor, those processes will
timeshare, but, inside UML, will appear to be running simultaneously.
If the host is a multiprocessor, then UML processes may run
simultaneously, depending on the host scheduler.
This, however, is supported only in TT mode. So, if you use the SKAS
patch on your host, switching to TT mode and enabling SMP usually
gives you worse performances.
Also, since the support for SMP has been under-developed, there could
be some bugs being exposed by enabling SMP.
If you don't know what to do, say N.
config NR_CPUS
int "Maximum number of CPUs (2-32)"
range 2 32
depends on SMP
default "32"
config HIGHMEM
bool "Highmem support"
depends on !64BIT && BROKEN

View file

@ -98,16 +98,8 @@ struct cpuinfo_um {
extern struct cpuinfo_um boot_cpu_data;
#define my_cpu_data cpu_data[smp_processor_id()]
#ifdef CONFIG_SMP
extern struct cpuinfo_um cpu_data[];
#define current_cpu_data cpu_data[smp_processor_id()]
#else
#define cpu_data (&boot_cpu_data)
#define current_cpu_data boot_cpu_data
#endif
#define KSTK_REG(tsk, reg) get_thread_reg(reg, &tsk->thread.switch_buf)
extern unsigned long get_wchan(struct task_struct *p);

View file

@ -1,32 +1,6 @@
#ifndef __UM_SMP_H
#define __UM_SMP_H
#ifdef CONFIG_SMP
#include <linux/bitops.h>
#include <asm/current.h>
#include <linux/cpumask.h>
#define raw_smp_processor_id() (current_thread->cpu)
#define cpu_logical_map(n) (n)
#define cpu_number_map(n) (n)
extern int hard_smp_processor_id(void);
#define NO_PROC_ID -1
extern int ncpus;
static inline void smp_cpus_done(unsigned int maxcpus)
{
}
extern struct task_struct *idle_threads[NR_CPUS];
#else
#define hard_smp_processor_id() 0
#endif
#endif

View file

@ -12,7 +12,7 @@ clean-files :=
obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \
physmem.o process.o ptrace.o reboot.o sigio.o \
signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \
signal.o syscall.o sysrq.o time.o tlb.o trap.o \
um_arch.o umid.o maccess.o skas/
obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o

View file

@ -35,9 +35,6 @@ void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
struct irq_fd *irq_fd;
int n;
if (smp_sigio_handler())
return;
while (1) {
n = os_waiting_for_events(active_fds);
if (n <= 0) {

View file

@ -259,17 +259,6 @@ int strlen_user_proc(char __user *str)
return strlen_user(str);
}
int smp_sigio_handler(void)
{
#ifdef CONFIG_SMP
int cpu = current_thread_info()->cpu;
IPI_handler(cpu);
if (cpu != 0)
return 1;
#endif
return 0;
}
int cpu(void)
{
return current_thread_info()->cpu;

View file

@ -21,9 +21,7 @@ static int __init start_kernel_proc(void *unused)
cpu_tasks[0].pid = pid;
cpu_tasks[0].task = current;
#ifdef CONFIG_SMP
init_cpu_online(get_cpu_mask(0));
#endif
start_kernel();
return 0;
}

View file

@ -1,238 +0,0 @@
/*
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <linux/percpu.h>
#include <asm/pgalloc.h>
#include <asm/tlb.h>
#ifdef CONFIG_SMP
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/threads.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/hardirq.h>
#include <asm/smp.h>
#include <asm/processor.h>
#include <asm/spinlock.h>
#include <kern.h>
#include <irq_user.h>
#include <os.h>
/* Per CPU bogomips and other parameters
* The only piece used here is the ipi pipe, which is set before SMP is
* started and never changed.
*/
struct cpuinfo_um cpu_data[NR_CPUS];
/* A statistic, can be a little off */
int num_reschedules_sent = 0;
/* Not changed after boot */
struct task_struct *idle_threads[NR_CPUS];
void smp_send_reschedule(int cpu)
{
os_write_file(cpu_data[cpu].ipi_pipe[1], "R", 1);
num_reschedules_sent++;
}
void smp_send_stop(void)
{
int i;
printk(KERN_INFO "Stopping all CPUs...");
for (i = 0; i < num_online_cpus(); i++) {
if (i == current_thread->cpu)
continue;
os_write_file(cpu_data[i].ipi_pipe[1], "S", 1);
}
printk(KERN_CONT "done\n");
}
static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
static cpumask_t cpu_callin_map = CPU_MASK_NONE;
static int idle_proc(void *cpup)
{
int cpu = (int) cpup, err;
err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1);
if (err < 0)
panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
os_set_fd_async(cpu_data[cpu].ipi_pipe[0]);
wmb();
if (cpu_test_and_set(cpu, cpu_callin_map)) {
printk(KERN_ERR "huh, CPU#%d already present??\n", cpu);
BUG();
}
while (!cpu_isset(cpu, smp_commenced_mask))
cpu_relax();
notify_cpu_starting(cpu);
set_cpu_online(cpu, true);
default_idle();
return 0;
}
static struct task_struct *idle_thread(int cpu)
{
struct task_struct *new_task;
current->thread.request.u.thread.proc = idle_proc;
current->thread.request.u.thread.arg = (void *) cpu;
new_task = fork_idle(cpu);
if (IS_ERR(new_task))
panic("copy_process failed in idle_thread, error = %ld",
PTR_ERR(new_task));
cpu_tasks[cpu] = ((struct cpu_task)
{ .pid = new_task->thread.mode.tt.extern_pid,
.task = new_task } );
idle_threads[cpu] = new_task;
panic("skas mode doesn't support SMP");
return new_task;
}
void smp_prepare_cpus(unsigned int maxcpus)
{
struct task_struct *idle;
unsigned long waittime;
int err, cpu, me = smp_processor_id();
int i;
for (i = 0; i < ncpus; ++i)
set_cpu_possible(i, true);
set_cpu_online(me, true);
cpu_set(me, cpu_callin_map);
err = os_pipe(cpu_data[me].ipi_pipe, 1, 1);
if (err < 0)
panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
os_set_fd_async(cpu_data[me].ipi_pipe[0]);
for (cpu = 1; cpu < ncpus; cpu++) {
printk(KERN_INFO "Booting processor %d...\n", cpu);
idle = idle_thread(cpu);
init_idle(idle, cpu);
waittime = 200000000;
while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
cpu_relax();
printk(KERN_INFO "%s\n",
cpu_isset(cpu, cpu_calling_map) ? "done" : "failed");
}
}
void smp_prepare_boot_cpu(void)
{
set_cpu_online(smp_processor_id(), true);
}
int __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
cpu_set(cpu, smp_commenced_mask);
while (!cpu_online(cpu))
mb();
return 0;
}
int setup_profiling_timer(unsigned int multiplier)
{
printk(KERN_INFO "setup_profiling_timer\n");
return 0;
}
void smp_call_function_slave(int cpu);
void IPI_handler(int cpu)
{
unsigned char c;
int fd;
fd = cpu_data[cpu].ipi_pipe[0];
while (os_read_file(fd, &c, 1) == 1) {
switch (c) {
case 'C':
smp_call_function_slave(cpu);
break;
case 'R':
scheduler_ipi();
break;
case 'S':
printk(KERN_INFO "CPU#%d stopping\n", cpu);
while (1)
pause();
break;
default:
printk(KERN_ERR "CPU#%d received unknown IPI [%c]!\n",
cpu, c);
break;
}
}
}
int hard_smp_processor_id(void)
{
return pid_to_processor_id(os_getpid());
}
static DEFINE_SPINLOCK(call_lock);
static atomic_t scf_started;
static atomic_t scf_finished;
static void (*func)(void *info);
static void *info;
void smp_call_function_slave(int cpu)
{
atomic_inc(&scf_started);
(*func)(info);
atomic_inc(&scf_finished);
}
int smp_call_function(void (*_func)(void *info), void *_info, int wait)
{
int cpus = num_online_cpus() - 1;
int i;
if (!cpus)
return 0;
/* Can deadlock when called with interrupts disabled */
WARN_ON(irqs_disabled());
spin_lock_bh(&call_lock);
atomic_set(&scf_started, 0);
atomic_set(&scf_finished, 0);
func = _func;
info = _info;
for_each_online_cpu(i)
os_write_file(cpu_data[i].ipi_pipe[1], "C", 1);
while (atomic_read(&scf_started) != cpus)
barrier();
if (wait)
while (atomic_read(&scf_finished) != cpus)
barrier();
spin_unlock_bh(&call_lock);
return 0;
}
#endif

View file

@ -66,12 +66,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
{
int index = 0;
#ifdef CONFIG_SMP
index = (struct cpuinfo_um *) v - cpu_data;
if (!cpu_online(index))
return 0;
#endif
seq_printf(m, "processor\t: %d\n", index);
seq_printf(m, "vendor_id\t: User Mode Linux\n");
seq_printf(m, "model name\t: UML\n");
@ -168,23 +162,6 @@ __uml_setup("debug", no_skas_debug_setup,
" this flag is not needed to run gdb on UML in skas mode\n\n"
);
#ifdef CONFIG_SMP
static int __init uml_ncpus_setup(char *line, int *add)
{
if (!sscanf(line, "%d", &ncpus)) {
printf("Couldn't parse [%s]\n", line);
return -1;
}
return 0;
}
__uml_setup("ncpus=", uml_ncpus_setup,
"ncpus=<# of desired CPUs>\n"
" This tells an SMP kernel how many virtual processors to start.\n\n"
);
#endif
static int __init Usage(char *line, int *add)
{
const char **p;
@ -380,15 +357,3 @@ void __init check_bugs(void)
void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
{
}
#ifdef CONFIG_SMP
void alternatives_smp_module_add(struct module *mod, char *name,
void *locks, void *locks_end,
void *text, void *text_end)
{
}
void alternatives_smp_module_del(struct module *mod)
{
}
#endif

View file

@ -36,22 +36,11 @@
#endif /* CONFIG_X86_PPRO_FENCE */
#define dma_wmb() barrier()
#ifdef CONFIG_SMP
#define smp_mb() mb()
#define smp_rmb() dma_rmb()
#define smp_wmb() barrier()
#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
#else /* CONFIG_SMP */
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
#define set_mb(var, value) do { var = value; barrier(); } while (0)
#endif /* CONFIG_SMP */
#define read_barrier_depends() do { } while (0)
#define smp_read_barrier_depends() do { } while (0)