x86/io: Speedup schedule out of I/O bitmap user
There is no requirement to update the TSS I/O bitmap when a thread using it is scheduled out and the incoming thread does not use it. For the permission check based on the TSS I/O bitmap the CPU calculates the memory location of the I/O bitmap by the address of the TSS and the io_bitmap_base member of the tss_struct. The easiest way to invalidate the I/O bitmap is to switch the offset to an address outside of the TSS limit. If an I/O instruction is issued from user space the TSS limit causes #GP to be raised in the same was as valid I/O bitmap with all bits set to 1 would do. This removes the extra work when an I/O bitmap using task is scheduled out and puts the burden on the rare I/O bitmap users when they are scheduled in. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
@@ -330,8 +330,23 @@ struct x86_hw_tss {
|
||||
#define IO_BITMAP_BITS 65536
|
||||
#define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
|
||||
#define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
|
||||
#define IO_BITMAP_OFFSET (offsetof(struct tss_struct, io_bitmap) - offsetof(struct tss_struct, x86_tss))
|
||||
#define INVALID_IO_BITMAP_OFFSET 0x8000
|
||||
|
||||
#define IO_BITMAP_OFFSET_VALID \
|
||||
(offsetof(struct tss_struct, io_bitmap) - \
|
||||
offsetof(struct tss_struct, x86_tss))
|
||||
|
||||
/*
|
||||
* sizeof(unsigned long) coming from an extra "long" at the end
|
||||
* of the iobitmap.
|
||||
*
|
||||
* -1? seg base+limit should be pointing to the address of the
|
||||
* last valid byte
|
||||
*/
|
||||
#define __KERNEL_TSS_LIMIT \
|
||||
(IO_BITMAP_OFFSET_VALID + IO_BITMAP_BYTES + sizeof(unsigned long) - 1)
|
||||
|
||||
/* Base offset outside of TSS_LIMIT so unpriviledged IO causes #GP */
|
||||
#define IO_BITMAP_OFFSET_INVALID (__KERNEL_TSS_LIMIT + 1)
|
||||
|
||||
struct entry_stack {
|
||||
unsigned long words[64];
|
||||
@@ -349,6 +364,15 @@ struct tss_struct {
|
||||
*/
|
||||
struct x86_hw_tss x86_tss;
|
||||
|
||||
/*
|
||||
* Store the dirty size of the last io bitmap offender. The next
|
||||
* one will have to do the cleanup as the switch out to a non io
|
||||
* bitmap user will just set x86_tss.io_bitmap_base to a value
|
||||
* outside of the TSS limit. So for sane tasks there is no need to
|
||||
* actually touch the io_bitmap at all.
|
||||
*/
|
||||
unsigned int io_bitmap_prev_max;
|
||||
|
||||
/*
|
||||
* The extra 1 is there because the CPU will access an
|
||||
* additional byte beyond the end of the IO permission
|
||||
@@ -360,16 +384,6 @@ struct tss_struct {
|
||||
|
||||
DECLARE_PER_CPU_PAGE_ALIGNED(struct tss_struct, cpu_tss_rw);
|
||||
|
||||
/*
|
||||
* sizeof(unsigned long) coming from an extra "long" at the end
|
||||
* of the iobitmap.
|
||||
*
|
||||
* -1? seg base+limit should be pointing to the address of the
|
||||
* last valid byte
|
||||
*/
|
||||
#define __KERNEL_TSS_LIMIT \
|
||||
(IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1)
|
||||
|
||||
/* Per CPU interrupt stacks */
|
||||
struct irq_stack {
|
||||
char stack[IRQ_STACK_SIZE];
|
||||
|
Reference in New Issue
Block a user