[PATCH] PER_CPU [2/4] - PER_CPU-init_tss

From: Shai Fultheim
Date: Fri Jul 09 2004 - 04:59:04 EST


[SECOND SUBBMITAL - Thanks for all the comments]
Andrew,

Please find below one out of collection of patched that move NR_CPU array
variables to the per-cpu area. Please consider applying, any comment will
highly appreciated.

Patches (altogether) tested using make allmodconfig, and defconfig, and
booted my system very nicely.

1/4. PER_CPU-cpu_gdt_table
2/4. PER_CPU-init_tss
3/4. PER_CPU-cpu_tlbstate
4/4. PER_CPU-irq_stat

PER_CPU-init_tss:
arch/i386/kernel/cpu/common.c | 2 +-
arch/i386/kernel/init_task.c | 7 ++-----
arch/i386/kernel/ioport.c | 2 +-
arch/i386/kernel/process.c | 4 ++--
arch/i386/kernel/sysenter.c | 2 +-
arch/i386/kernel/vm86.c | 4 ++--
arch/i386/power/cpu.c | 2 +-
include/asm-i386/processor.h | 4 ++--
8 files changed, 12 insertions(+), 15 deletions(-)

Signed-off-by: Martin Hicks <mort@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Shai Fultheim <shai@xxxxxxxxxxxx>

=================================================================================
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2004/07/09 00:43:12-07:00 shai@compile.(none)
# Many files:
# PER_CPU-init_tss
# Convert init_tss into a per_cpu variable. The only tricky bit is
# that the esp1 initaliztion is not needed since Linux never uses
# ring1. esp1 is initalized at 'enable_sep_cpu' for
# sysenter/sysexit.
#
# Signed-off-by: Martin Hicks <mort@xxxxxxxxxxxxxxxxxx>
# Signed-off-by: Shai Fultheim <shai@xxxxxxxxxxxx>
#
# include/asm-i386/processor.h
# 2004/07/09 00:41:50-07:00 shai@compile.(none) +2 -2
# PER_CPU-init_tss
#
# arch/i386/power/cpu.c
# 2004/07/09 00:41:50-07:00 shai@compile.(none) +1 -1
# PER_CPU-init_tss
#
# arch/i386/kernel/vm86.c
# 2004/07/09 00:41:50-07:00 shai@compile.(none) +2 -2
# PER_CPU-init_tss
#
# arch/i386/kernel/sysenter.c
# 2004/07/09 00:41:50-07:00 shai@compile.(none) +1 -1
# PER_CPU-init_tss
#
# arch/i386/kernel/process.c
# 2004/07/09 00:41:50-07:00 shai@compile.(none) +2 -2
# PER_CPU-init_tss
#
# arch/i386/kernel/ioport.c
# 2004/07/09 00:41:50-07:00 shai@compile.(none) +1 -1
# PER_CPU-init_tss
#
# arch/i386/kernel/init_task.c
# 2004/07/09 00:41:50-07:00 shai@compile.(none) +2 -5
# PER_CPU-init_tss
#
# arch/i386/kernel/cpu/common.c
# 2004/07/09 00:41:50-07:00 shai@compile.(none) +1 -1
# PER_CPU-init_tss
#
diff -Nru a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
--- a/arch/i386/kernel/cpu/common.c 2004-07-09 01:34:21 -07:00
+++ b/arch/i386/kernel/cpu/common.c 2004-07-09 01:34:21 -07:00
@@ -504,7 +504,7 @@
void __init cpu_init (void)
{
int cpu = smp_processor_id();
- struct tss_struct * t = init_tss + cpu;
+ struct tss_struct * t = &per_cpu(init_tss, cpu);
struct thread_struct *thread = &current->thread;

if (test_and_set_bit(cpu, &cpu_initialized)) {
diff -Nru a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c
--- a/arch/i386/kernel/init_task.c 2004-07-09 01:34:21 -07:00
+++ b/arch/i386/kernel/init_task.c 2004-07-09 01:34:21 -07:00
@@ -40,10 +40,7 @@

/*
* per-CPU TSS segments. Threads are completely 'soft' on Linux,
- * no more per-task TSS's. The TSS size is kept cacheline-aligned
- * so they are allowed to end up in the .data.cacheline_aligned
- * section. Since TSS's are completely CPU-local, we want them
- * on exact cacheline boundaries, to eliminate cacheline ping-pong.
+ * no more per-task TSS's.
*/
-struct tss_struct init_tss[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1] = INIT_TSS };
+DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp = INIT_TSS;

diff -Nru a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c
--- a/arch/i386/kernel/ioport.c 2004-07-09 01:34:21 -07:00
+++ b/arch/i386/kernel/ioport.c 2004-07-09 01:34:21 -07:00
@@ -83,7 +83,7 @@
* do it in the per-thread copy and in the TSS ...
*/
set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
- tss = init_tss + get_cpu();
+ tss = &per_cpu(init_tss, get_cpu());
if (tss->io_bitmap_base == IO_BITMAP_OFFSET) { /* already active? */
set_bitmap(tss->io_bitmap, from, num, !turn_on);
} else {
diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
--- a/arch/i386/kernel/process.c 2004-07-09 01:34:21 -07:00
+++ b/arch/i386/kernel/process.c 2004-07-09 01:34:21 -07:00
@@ -298,7 +298,7 @@
/* The process may have allocated an io port bitmap... nuke it. */
if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) {
int cpu = get_cpu();
- struct tss_struct *tss = init_tss + cpu;
+ struct tss_struct *tss = &per_cpu(init_tss, cpu);
kfree(tsk->thread.io_bitmap_ptr);
tsk->thread.io_bitmap_ptr = NULL;
tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
@@ -507,7 +507,7 @@
struct thread_struct *prev = &prev_p->thread,
*next = &next_p->thread;
int cpu = smp_processor_id();
- struct tss_struct *tss = init_tss + cpu;
+ struct tss_struct *tss = &per_cpu(init_tss, cpu);

/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */

diff -Nru a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c
--- a/arch/i386/kernel/sysenter.c 2004-07-09 01:34:21 -07:00
+++ b/arch/i386/kernel/sysenter.c 2004-07-09 01:34:21 -07:00
@@ -24,7 +24,7 @@
void enable_sep_cpu(void *info)
{
int cpu = get_cpu();
- struct tss_struct *tss = init_tss + cpu;
+ struct tss_struct *tss = &per_cpu(init_tss, cpu);

tss->ss1 = __KERNEL_CS;
tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
--- a/arch/i386/kernel/vm86.c 2004-07-09 01:34:21 -07:00
+++ b/arch/i386/kernel/vm86.c 2004-07-09 01:34:21 -07:00
@@ -121,7 +121,7 @@
do_exit(SIGSEGV);
}

- tss = init_tss + get_cpu();
+ tss = &per_cpu(init_tss, get_cpu());
current->thread.esp0 = current->thread.saved_esp0;
current->thread.sysenter_cs = __KERNEL_CS;
load_esp0(tss, &current->thread);
@@ -303,7 +303,7 @@
asm volatile("movl %%fs,%0":"=m" (tsk->thread.saved_fs));
asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs));

- tss = init_tss + get_cpu();
+ tss = &per_cpu(init_tss, get_cpu());
tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
if (cpu_has_sep)
tsk->thread.sysenter_cs = 0;
diff -Nru a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c
--- a/arch/i386/power/cpu.c 2004-07-09 01:34:21 -07:00
+++ b/arch/i386/power/cpu.c 2004-07-09 01:34:21 -07:00
@@ -83,7 +83,7 @@
static void fix_processor_context(void)
{
int cpu = smp_processor_id();
- struct tss_struct * t = init_tss + cpu;
+ struct tss_struct * t = &per_cpu(init_tss, cpu);

set_tss_desc(cpu,t); /* This just modifies memory; should not be necessary. But... This is necessary, because 386
hardware has concept of busy TSS or some similar stupidity. */
per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_TSS].b &= 0xfffffdff;
diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h
--- a/include/asm-i386/processor.h 2004-07-09 01:34:21 -07:00
+++ b/include/asm-i386/processor.h 2004-07-09 01:34:21 -07:00
@@ -19,6 +19,7 @@
#include <linux/cache.h>
#include <linux/config.h>
#include <linux/threads.h>
+#include <asm/percpu.h>

/* flag for disabling the tsc */
extern int tsc_disable;
@@ -84,8 +85,8 @@

extern struct cpuinfo_x86 boot_cpu_data;
extern struct cpuinfo_x86 new_cpu_data;
-extern struct tss_struct init_tss[NR_CPUS];
extern struct tss_struct doublefault_tss;
+DECLARE_PER_CPU(struct tss_struct, init_tss);

#ifdef CONFIG_SMP
extern struct cpuinfo_x86 cpu_data[];
@@ -439,7 +440,6 @@
#define INIT_TSS { \
.esp0 = sizeof(init_stack) + (long)&init_stack, \
.ss0 = __KERNEL_DS, \
- .esp1 = sizeof(init_tss[0]) + (long)&init_tss[0], \
.ss1 = __KERNEL_CS, \
.ldt = GDT_ENTRY_LDT, \
.io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \
=================================================================================

 
-----------------
Shai Fultheim
Scalex86.org


Attachment: rev-1.1820.patch
Description: Binary data