Commit ded80dca authored by Benjamin LaHaise's avatar Benjamin LaHaise Committed by Linus Torvalds

[PATCH] 2.5.20 x86 iobitmap cleanup

This makes the IO bitmap allocations a separately allocated structure,
shrinking the default task size.

We alloc it in sys_ioperm() and copy_thread() and frees in
exit_thread().  It also gets rid of the IO_BITMAP_SIZE+1 crap, as only
the tss actually needs the tail long, and we weren't copying it into the
bitmap anyways.
parent da615ea7
...@@ -10,10 +10,10 @@ ...@@ -10,10 +10,10 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/slab.h>
/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value) static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value)
...@@ -66,12 +66,16 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) ...@@ -66,12 +66,16 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
* IO bitmap up. ioperm() is much less timing critical than clone(), * IO bitmap up. ioperm() is much less timing critical than clone(),
* this is why we delay this operation until now: * this is why we delay this operation until now:
*/ */
if (!t->ioperm) { if (!t->ts_io_bitmap) {
unsigned long *bitmap;
bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
if (!bitmap)
return -ENOMEM;
/* /*
* just in case ... * just in case ...
*/ */
memset(t->io_bitmap,0xff,(IO_BITMAP_SIZE+1)*4); memset(bitmap, 0xff, IO_BITMAP_BYTES);
t->ioperm = 1; t->ts_io_bitmap = bitmap;
/* /*
* this activates it in the TSS * this activates it in the TSS
*/ */
...@@ -81,7 +85,7 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) ...@@ -81,7 +85,7 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
/* /*
* do it in the per-thread copy and in the TSS ... * do it in the per-thread copy and in the TSS ...
*/ */
set_bitmap(t->io_bitmap, from, num, !turn_on); set_bitmap(t->ts_io_bitmap, from, num, !turn_on);
set_bitmap(tss->io_bitmap, from, num, !turn_on); set_bitmap(tss->io_bitmap, from, num, !turn_on);
return 0; return 0;
......
...@@ -509,7 +509,13 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ...@@ -509,7 +509,13 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
*/ */
void exit_thread(void) void exit_thread(void)
{ {
/* nothing to do ... */ struct task_struct *tsk = current;
/* The process may have allocated an io port bitmap... nuke it. */
if (unlikely(NULL != tsk->thread.ts_io_bitmap)) {
kfree(tsk->thread.ts_io_bitmap);
tsk->thread.ts_io_bitmap = NULL;
}
} }
void flush_thread(void) void flush_thread(void)
...@@ -549,6 +555,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, ...@@ -549,6 +555,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
struct task_struct * p, struct pt_regs * regs) struct task_struct * p, struct pt_regs * regs)
{ {
struct pt_regs * childregs; struct pt_regs * childregs;
struct task_struct *tsk;
childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
struct_cpy(childregs, regs); struct_cpy(childregs, regs);
...@@ -563,8 +570,17 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, ...@@ -563,8 +570,17 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
savesegment(fs,p->thread.fs); savesegment(fs,p->thread.fs);
savesegment(gs,p->thread.gs); savesegment(gs,p->thread.gs);
unlazy_fpu(current); tsk = current;
struct_cpy(&p->thread.i387, &current->thread.i387); unlazy_fpu(tsk);
struct_cpy(&p->thread.i387, &tsk->thread.i387);
if (unlikely(NULL != tsk->thread.ts_io_bitmap)) {
p->thread.ts_io_bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
if (!p->thread.ts_io_bitmap)
return -ENOMEM;
memcpy(p->thread.ts_io_bitmap, tsk->thread.ts_io_bitmap,
IO_BITMAP_BYTES);
}
return 0; return 0;
} }
...@@ -685,8 +701,8 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p) ...@@ -685,8 +701,8 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
loaddebug(next, 7); loaddebug(next, 7);
} }
if (unlikely(prev->ioperm || next->ioperm)) { if (unlikely(prev->ts_io_bitmap || next->ts_io_bitmap)) {
if (next->ioperm) { if (next->ts_io_bitmap) {
/* /*
* 4 cachelines copy ... not good, but not that * 4 cachelines copy ... not good, but not that
* bad either. Anyone got something better? * bad either. Anyone got something better?
...@@ -695,8 +711,8 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p) ...@@ -695,8 +711,8 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
* and playing VM tricks to switch the IO bitmap * and playing VM tricks to switch the IO bitmap
* is not really acceptable.] * is not really acceptable.]
*/ */
memcpy(tss->io_bitmap, next->io_bitmap, memcpy(tss->io_bitmap, next->ts_io_bitmap,
IO_BITMAP_SIZE*sizeof(unsigned long)); IO_BITMAP_BYTES);
tss->bitmap = IO_BITMAP_OFFSET; tss->bitmap = IO_BITMAP_OFFSET;
} else } else
/* /*
......
...@@ -267,6 +267,7 @@ extern unsigned int mca_pentium_flag; ...@@ -267,6 +267,7 @@ extern unsigned int mca_pentium_flag;
* Size of io_bitmap in longwords: 32 is ports 0-0x3ff. * Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
*/ */
#define IO_BITMAP_SIZE 32 #define IO_BITMAP_SIZE 32
#define IO_BITMAP_BYTES (IO_BITMAP_SIZE * 4)
#define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap) #define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
#define INVALID_IO_BITMAP_OFFSET 0x8000 #define INVALID_IO_BITMAP_OFFSET 0x8000
...@@ -370,8 +371,7 @@ struct thread_struct { ...@@ -370,8 +371,7 @@ struct thread_struct {
unsigned long screen_bitmap; unsigned long screen_bitmap;
unsigned long v86flags, v86mask, v86mode, saved_esp0; unsigned long v86flags, v86mask, v86mode, saved_esp0;
/* IO permissions */ /* IO permissions */
int ioperm; unsigned long *ts_io_bitmap;
unsigned long io_bitmap[IO_BITMAP_SIZE+1];
}; };
#define INIT_THREAD { \ #define INIT_THREAD { \
...@@ -381,7 +381,7 @@ struct thread_struct { ...@@ -381,7 +381,7 @@ struct thread_struct {
0, 0, 0, \ 0, 0, 0, \
{ { 0, }, }, /* 387 state */ \ { { 0, }, }, /* 387 state */ \
0,0,0,0,0,0, \ 0,0,0,0,0,0, \
0,{~0,} /* io permissions */ \ NULL, /* io permissions */ \
} }
#define INIT_TSS { \ #define INIT_TSS { \
......
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