summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAlbert Cahalan <albert.cahalan@ccur.com>2003-08-19 21:53:41 -0700
committerLinus Torvalds <torvalds@home.osdl.org>2003-08-19 21:53:41 -0700
commit0b401e2588128c9d0471a1de31800a105cd7bb43 (patch)
tree0bb4a1300341e596abfacf9c67e0c92dd754138b /include
parente14720a157f5d8745006f44520dfa3b8ac498328 (diff)
[PATCH] IO port bitmap cleanups, x86-64 oops fix
This patch brings x86-64 and i386 closer together, eliminating an oops that LTP test ioperm02.c causes on x86-64. An IO port permission bitmap must be followed by an extra 0xff. (Add comments to that effect, to avoid the problem in the future).
Diffstat (limited to 'include')
-rw-r--r--include/asm-i386/processor.h33
-rw-r--r--include/asm-x86_64/processor.h23
2 files changed, 40 insertions, 16 deletions
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index ac14135d83ba..a48d81758ba1 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -291,10 +291,11 @@ extern unsigned int mca_pentium_flag;
#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
/*
- * Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
+ * Size of io_bitmap, covering ports 0 to 0x3ff.
*/
-#define IO_BITMAP_SIZE 32
-#define IO_BITMAP_BYTES (IO_BITMAP_SIZE * 4)
+#define IO_BITMAP_BITS 1024
+#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)
#define INVALID_IO_BITMAP_OFFSET 0x8000
@@ -373,8 +374,14 @@ struct tss_struct {
unsigned short fs, __fsh;
unsigned short gs, __gsh;
unsigned short ldt, __ldth;
- unsigned short trace, bitmap;
- unsigned long io_bitmap[IO_BITMAP_SIZE+1];
+ unsigned short trace, io_bitmap_base;
+ /*
+ * The extra 1 is there because the CPU will access an
+ * additional byte beyond the end of the IO permission
+ * bitmap. The extra byte must be all 1 bits, and must
+ * be within the limit.
+ */
+ unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
/*
* pads the TSS to be cacheline-aligned (size is 0x100)
*/
@@ -383,7 +390,7 @@ struct tss_struct {
* .. and then another 0x100 bytes for emergency kernel stack
*/
unsigned long stack[64];
-};
+} __attribute__((packed));
struct thread_struct {
/* cached TLS descriptors. */
@@ -405,22 +412,28 @@ struct thread_struct {
unsigned long v86flags, v86mask, saved_esp0;
unsigned int saved_fs, saved_gs;
/* IO permissions */
- unsigned long *ts_io_bitmap;
+ unsigned long *io_bitmap_ptr;
};
#define INIT_THREAD { \
.vm86_info = NULL, \
- .ts_io_bitmap = NULL, \
+ .io_bitmap_ptr = NULL, \
}
+/*
+ * Note that the .io_bitmap member must be extra-big. This is because
+ * the CPU will access an additional byte beyond the end of the IO
+ * permission bitmap. The extra byte must be all 1 bits, and must
+ * be within the limit.
+ */
#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, \
- .bitmap = INVALID_IO_BITMAP_OFFSET, \
- .io_bitmap = { [ 0 ... IO_BITMAP_SIZE ] = ~0 }, \
+ .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \
+ .io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 }, \
}
static inline void load_esp0(struct tss_struct *tss, unsigned long esp0)
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index 2ba01da9795f..12714f573352 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -178,10 +178,11 @@ static inline void clear_in_cr4 (unsigned long mask)
(test_thread_flag(TIF_IA32) ? TASK_UNMAPPED_32 : TASK_UNMAPPED_64)
/*
- * Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
+ * Size of io_bitmap, covering ports 0 to 0x3ff.
*/
-#define IO_BITMAP_SIZE 32
-#define IO_BITMAP_BYTES (IO_BITMAP_SIZE * 4)
+#define IO_BITMAP_BITS 1024
+#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)
#define INVALID_IO_BITMAP_OFFSET 0x8000
@@ -213,8 +214,18 @@ struct tss_struct {
u32 reserved3;
u32 reserved4;
u16 reserved5;
- u16 io_map_base;
- u32 io_bitmap[IO_BITMAP_SIZE];
+ u16 io_bitmap_base;
+ /*
+ * The extra 1 is there because the CPU will access an
+ * additional byte beyond the end of the IO permission
+ * bitmap. The extra byte must be all 1 bits, and must
+ * be within the limit. Thus we have:
+ *
+ * 128 bytes, the bitmap itself, for ports 0..0x3ff
+ * 8 bytes, for an extra "long" of ~0UL
+ */
+ unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
+ u32 __cacheline_filler[4]; /* size is 0x100 */
} __attribute__((packed)) ____cacheline_aligned;
struct thread_struct {
@@ -238,7 +249,7 @@ struct thread_struct {
/* IO permissions. the bitmap could be moved into the GDT, that would make
switch faster for a limited number of ioperm using tasks. -AK */
int ioperm;
- u32 *io_bitmap_ptr;
+ unsigned long *io_bitmap_ptr;
/* cached TLS descriptors. */
u64 tls_array[GDT_ENTRY_TLS_ENTRIES];
};