Changeset 2382d09 in mainline


Ignore:
Timestamp:
2006-04-29T15:01:41Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
407862e
Parents:
69a5600
Message:

Improve SYS_IOSPACE_ENABLE support.
The general protection fault handler now contains
code to service early I/O Permission bitmap faults.

Location:
arch
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • arch/amd64/include/cpu.h

    r69a5600 r2382d09  
    5858        int stepping;
    5959        struct tss *tss;
     60       
     61        count_t iomapver_copy;  /** Copy of TASK's I/O Permission bitmap generation count. */
    6062};
    6163
  • arch/amd64/include/proc/task.h

    r69a5600 r2382d09  
    3535
    3636typedef struct {
    37         bitmap_t iomap;
     37        count_t iomapver;       /**< I/O Permission bitmap Generation counter. */
     38        bitmap_t iomap;         /**< I/O Permission bitmap. */
    3839} task_arch_t;
    3940
  • arch/amd64/src/ddi/ddi.c

    r69a5600 r2382d09  
    2828
    2929#include <ddi/ddi.h>
     30#include <arch/ddi/ddi.h>
    3031#include <proc/task.h>
    3132#include <arch/types.h>
     
    3637#include <errno.h>
    3738#include <arch/cpu.h>
     39#include <arch.h>
    3840
    3941/** Enable I/O space range for task.
     
    9092        bitmap_clear_range(&task->arch.iomap, (index_t) ioaddr, (count_t) size);
    9193
     94        /*
     95         * Increment I/O Permission bitmap generation counter.
     96         */
     97        task->arch.iomapver++;
     98
    9299        return 0;
    93100}
     
    106113        return 0;
    107114}
     115
     116/** Install I/O Permission bitmap.
     117 *
     118 * Current task's I/O permission bitmap, if any, is installed
     119 * in the current CPU's TSS.
     120 *
     121 * Interrupts must be disabled prior this call.
     122 */
     123void io_perm_bitmap_install(void)
     124{
     125        count_t bits;
     126        ptr_16_64_t cpugdtr;
     127        descriptor_t *gdt_p;
     128        tss_descriptor_t *tss_desc;
     129        count_t ver;
     130
     131        /* First, copy the I/O Permission Bitmap. */
     132        spinlock_lock(&TASK->lock);
     133        ver = TASK->arch.iomapver;
     134        if ((bits = TASK->arch.iomap.bits)) {
     135                bitmap_t iomap;
     136       
     137                ASSERT(TASK->arch.iomap.map);
     138                bitmap_initialize(&iomap, CPU->arch.tss->iomap, TSS_IOMAP_SIZE * 8);
     139                bitmap_copy(&iomap, &TASK->arch.iomap, TASK->arch.iomap.bits);
     140                /*
     141                 * It is safe to set the trailing eight bits because of the extra
     142                 * convenience byte in TSS_IOMAP_SIZE.
     143                 */
     144                bitmap_set_range(&iomap, TASK->arch.iomap.bits, 8);
     145        }
     146        spinlock_unlock(&TASK->lock);
     147
     148        /* Second, adjust TSS segment limit. */
     149        gdtr_store(&cpugdtr);
     150        gdt_p = (descriptor_t *) cpugdtr.base;
     151        gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + BITS2BYTES(bits) - 1);
     152        gdtr_load(&cpugdtr);
     153       
     154        /*
     155         * Before we load new TSS limit, the current TSS descriptor
     156         * type must be changed to describe inactive TSS.
     157         */
     158        tss_desc = (tss_descriptor_t *) &gdt_p[TSS_DES];
     159        tss_desc->type = AR_TSS;
     160        tr_load(gdtselector(TSS_DES));
     161       
     162        /*
     163         * Update the generation count so that faults caused by
     164         * early accesses can be serviced.
     165         */
     166        CPU->arch.iomapver_copy = ver;
     167}
  • arch/amd64/src/interrupt.c

    r69a5600 r2382d09  
    4242#include <proc/scheduler.h>
    4343#include <proc/thread.h>
     44#include <proc/task.h>
     45#include <synch/spinlock.h>
     46#include <arch/ddi/ddi.h>
    4447
    4548void print_info_errcode(int n, istate_t *istate)
     
    7982}
    8083
     84/** General Protection Fault. */
    8185void gp_fault(int n, istate_t *istate)
    8286{
     87        if (TASK) {
     88                count_t ver;
     89
     90                spinlock_lock(&TASK->lock);
     91                ver = TASK->arch.iomapver;
     92                spinlock_unlock(&TASK->lock);
     93
     94                if (CPU->arch.iomapver_copy != ver) {
     95                        /*
     96                         * This fault can be caused by an early access
     97                         * to I/O port because of an out-dated
     98                         * I/O Permission bitmap installed on CPU.
     99                         * Install the fresh copy and restart
     100                         * the instruction.
     101                         */
     102                        io_perm_bitmap_install();
     103                        return;
     104                }
     105        }
     106
    83107        print_info_errcode(n, istate);
    84108        panic("general protection fault\n");
  • arch/amd64/src/proc/scheduler.c

    r69a5600 r2382d09  
    3737#include <print.h>
    3838#include <arch/pm.h>
    39 #include <adt/bitmap.h>
     39#include <arch/ddi/ddi.h>
    4040
    4141/** Perform amd64 specific tasks needed before the new task is run.
     
    4545void before_task_runs_arch(void)
    4646{
    47         count_t bits;
    48         ptr_16_64_t cpugdtr;
    49         descriptor_t *gdt_p;
    50         tss_descriptor_t *tss_desc;
    51 
    52         /*
    53          * Switch the I/O Permission Bitmap, if necessary.
    54          */
    55          
    56         /* First, copy the I/O Permission Bitmap. */
    57         spinlock_lock(&TASK->lock);
    58         if ((bits = TASK->arch.iomap.bits)) {
    59                 bitmap_t iomap;
    60        
    61                 ASSERT(TASK->arch.iomap.map);
    62                 bitmap_initialize(&iomap, CPU->arch.tss->iomap, TSS_IOMAP_SIZE * 8);
    63                 bitmap_copy(&iomap, &TASK->arch.iomap, TASK->arch.iomap.bits);
    64                 /*
    65                  * It is safe to set the trailing eight bits because of the extra
    66                  * convenience byte in TSS_IOMAP_SIZE.
    67                  */
    68                 bitmap_set_range(&iomap, TASK->arch.iomap.bits, 8);
    69         }
    70         spinlock_unlock(&TASK->lock);
    71 
    72         /* Second, adjust TSS segment limit. */
    73         gdtr_store(&cpugdtr);
    74         gdt_p = (descriptor_t *) cpugdtr.base;
    75         gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + BITS2BYTES(bits) - 1);
    76         gdtr_load(&cpugdtr);
    77        
    78         /*
    79          * Before we load new TSS limit, the current TSS descriptor
    80          * type must be changed to describe inactive TSS.
    81          */
    82         tss_desc = (tss_descriptor_t *) &gdt_p[TSS_DES];
    83         tss_desc->type = AR_TSS;
    84         tr_load(gdtselector(TSS_DES));
     47        io_perm_bitmap_install();
    8548}
    8649
  • arch/ia32/include/cpu.h

    r69a5600 r2382d09  
    4343        int stepping;
    4444        struct tss *tss;
     45       
     46        count_t iomapver_copy;  /** Copy of TASK's I/O Permission bitmap generation count. */
    4547};
    4648
  • arch/ia32/include/proc/task.h

    r69a5600 r2382d09  
    3535
    3636typedef struct {
    37         bitmap_t iomap;
     37        count_t iomapver;       /**< I/O Permission bitmap Generation counter. */
     38        bitmap_t iomap;         /**< I/O Permission bitmap. */
    3839} task_arch_t;
    3940
  • arch/ia32/src/ddi/ddi.c

    r69a5600 r2382d09  
    2828
    2929#include <ddi/ddi.h>
     30#include <arch/ddi/ddi.h>
    3031#include <proc/task.h>
    3132#include <arch/types.h>
     
    3637#include <errno.h>
    3738#include <arch/cpu.h>
     39#include <cpu.h>
     40#include <arch.h>
    3841
    3942/** Enable I/O space range for task.
     
    9093        bitmap_clear_range(&task->arch.iomap, (index_t) ioaddr, (count_t) size);
    9194
     95        /*
     96         * Increment I/O Permission bitmap generation counter.
     97         */
     98        task->arch.iomapver++;
     99
    92100        return 0;
    93101}
     
    106114        return 0;
    107115}
     116
     117/** Install I/O Permission bitmap.
     118 *
     119 * Current task's I/O permission bitmap, if any, is installed
     120 * in the current CPU's TSS.
     121 *
     122 * Interrupts must be disabled prior this call.
     123 */
     124void io_perm_bitmap_install(void)
     125{
     126        count_t bits;
     127        ptr_16_32_t cpugdtr;
     128        descriptor_t *gdt_p;
     129        count_t ver;
     130
     131        /* First, copy the I/O Permission Bitmap. */
     132        spinlock_lock(&TASK->lock);
     133        ver = TASK->arch.iomapver;
     134        if ((bits = TASK->arch.iomap.bits)) {
     135                bitmap_t iomap;
     136       
     137                ASSERT(TASK->arch.iomap.map);
     138                bitmap_initialize(&iomap, CPU->arch.tss->iomap, TSS_IOMAP_SIZE * 8);
     139                bitmap_copy(&iomap, &TASK->arch.iomap, TASK->arch.iomap.bits);
     140                /*
     141                 * It is safe to set the trailing eight bits because of the extra
     142                 * convenience byte in TSS_IOMAP_SIZE.
     143                 */
     144                bitmap_set_range(&iomap, TASK->arch.iomap.bits, 8);
     145        }
     146        spinlock_unlock(&TASK->lock);
     147
     148        /* Second, adjust TSS segment limit. */
     149        gdtr_store(&cpugdtr);
     150        gdt_p = (descriptor_t *) cpugdtr.base;
     151        gdt_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + BITS2BYTES(bits) - 1);
     152        gdtr_load(&cpugdtr);
     153
     154        /*
     155         * Before we load new TSS limit, the current TSS descriptor
     156         * type must be changed to describe inactive TSS.
     157         */
     158        gdt_p[TSS_DES].access = AR_PRESENT | AR_TSS | DPL_KERNEL;
     159        tr_load(selector(TSS_DES));
     160       
     161        /*
     162         * Update the generation count so that faults caused by
     163         * early accesses can be serviced.
     164         */
     165        CPU->arch.iomapver_copy = ver;
     166}
  • arch/ia32/src/interrupt.c

    r69a5600 r2382d09  
    4141#include <symtab.h>
    4242#include <proc/thread.h>
     43#include <proc/task.h>
     44#include <synch/spinlock.h>
     45#include <arch/ddi/ddi.h>
    4346
    4447/*
     
    7982}
    8083
     84/** General Protection Fault. */
    8185void gp_fault(int n, istate_t *istate)
    8286{
     87        if (TASK) {
     88                count_t ver;
     89               
     90                spinlock_lock(&TASK->lock);
     91                ver = TASK->arch.iomapver;
     92                spinlock_unlock(&TASK->lock);
     93       
     94                if (CPU->arch.iomapver_copy != ver) {
     95                        /*
     96                         * This fault can be caused by an early access
     97                         * to I/O port because of an out-dated
     98                         * I/O Permission bitmap installed on CPU.
     99                         * Install the fresh copy and restart
     100                         * the instruction.
     101                         */
     102                        io_perm_bitmap_install();
     103                        return;
     104                }
     105        }
     106
    83107        PRINT_INFO_ERRCODE(istate);
    84108        panic("general protection fault\n");
  • arch/ia32/src/proc/scheduler.c

    r69a5600 r2382d09  
    3636#include <arch/pm.h>
    3737#include <arch/asm.h>
    38 #include <adt/bitmap.h>
    39 #include <print.h>
     38#include <arch/ddi/ddi.h>
    4039
    4140/** Perform ia32 specific tasks needed before the new task is run.
     
    4544void before_task_runs_arch(void)
    4645{
    47         count_t bits;
    48         ptr_16_32_t cpugdtr;
    49         descriptor_t *gdt_p;
    50 
    51         /*
    52          * Switch the I/O Permission Bitmap, if necessary.
    53          */
    54 
    55         /* First, copy the I/O Permission Bitmap. */
    56         spinlock_lock(&TASK->lock);
    57         if ((bits = TASK->arch.iomap.bits)) {
    58                 bitmap_t iomap;
    59        
    60                 ASSERT(TASK->arch.iomap.map);
    61                 bitmap_initialize(&iomap, CPU->arch.tss->iomap, TSS_IOMAP_SIZE * 8);
    62                 bitmap_copy(&iomap, &TASK->arch.iomap, TASK->arch.iomap.bits);
    63                 /*
    64                  * It is safe to set the trailing eight bits because of the extra
    65                  * convenience byte in TSS_IOMAP_SIZE.
    66                  */
    67                 bitmap_set_range(&iomap, TASK->arch.iomap.bits, 8);
    68         }
    69         spinlock_unlock(&TASK->lock);
    70 
    71         /* Second, adjust TSS segment limit. */
    72         gdtr_store(&cpugdtr);
    73         gdt_p = (descriptor_t *) cpugdtr.base;
    74         gdt_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + BITS2BYTES(bits) - 1);
    75         gdtr_load(&cpugdtr);
    76 
    77         /*
    78          * Before we load new TSS limit, the current TSS descriptor
    79          * type must be changed to describe inactive TSS.
    80          */
    81         gdt_p[TSS_DES].access = AR_PRESENT | AR_TSS | DPL_KERNEL;
    82         tr_load(selector(TSS_DES));
     46        io_perm_bitmap_install();
    8347}
    8448
Note: See TracChangeset for help on using the changeset viewer.