diff options
| author | Albert Cahalan <albert.cahalan@ccur.com> | 2003-08-19 21:53:41 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.osdl.org> | 2003-08-19 21:53:41 -0700 |
| commit | 0b401e2588128c9d0471a1de31800a105cd7bb43 (patch) | |
| tree | 0bb4a1300341e596abfacf9c67e0c92dd754138b /include | |
| parent | e14720a157f5d8745006f44520dfa3b8ac498328 (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.h | 33 | ||||
| -rw-r--r-- | include/asm-x86_64/processor.h | 23 |
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]; }; |
