Ticket #7172: arch_selector.c

File arch_selector.c, 1.8 KB (added by stargatefan, 10 years ago)
Line 
1/*
2** Copyright 2002, Michael Noisternig. All rights reserved.
3** Distributed under the terms of the NewOS License.
4*/
5#include <boot/arch/i386/stage2.h>
6#include <kernel/arch/cpu.h>
7#include <kernel/smp.h>
8#include <kernel/int.h>
9
10#include <kernel/arch/i386/selector.h>
11
12#define MAX_SELECTORS (GDT_LIMIT/8)
13#define ENTRIES (MAX_SELECTORS/(sizeof(uint32)*8))
14
15static uint32 selector_bitmap[ENTRIES]
16 = { 0x000000ff }; // first 8 selectors reserved
17
18static selector_type *gdt_table;
19static struct gdt_idt_descr descr = { GDT_LIMIT - 1, NULL };
20
21void i386_selector_init( void *gdt )
22{
23 gdt_table = (selector_type *)gdt;
24 descr.b = (unsigned int *)gdt_table;
25}
26
27// creates a new selector in the gdt of given type (use SELECTOR macro)
28// IN: selector type
29// RET: selector that can be directly used for segment registers
30// 0 on error
31selector_id i386_selector_add( selector_type type )
32{
33 static int spinlock;
34 int state;
35 uint32 mask;
36 selector_id id = 0;
37 unsigned i;
38
39 state = int_disable_interrupts();
40 acquire_spinlock( &spinlock );
41
42 for ( i = 0; i < ENTRIES; i++ )
43 if ( selector_bitmap[i] != 0xffffffff ) { // found free place in there
44 id = i*sizeof(uint32)*8;
45 mask = 1;
46 while ( selector_bitmap[i] & mask ) {
47 mask <<= 1;
48 id++;
49 }
50 selector_bitmap[i] |= mask;
51 gdt_table[id] = type;
52 break;
53 }
54
55 release_spinlock( &spinlock );
56 int_restore_interrupts( state );
57
58 if ( id ) {
59 asm("lgdt %0;"
60 : : "m" (descr));
61 }
62
63 return id*8;
64}
65
66// removes a selector with given id from the gdt
67void i386_selector_remove( selector_id id )
68{
69 if ( id < 8*8 || id >= MAX_SELECTORS*8 )
70 return;
71
72 id /= 8;
73 gdt_table[id] = 0;
74
75 atomic_and( &selector_bitmap[id/32], ~(1<<(id&31)) );
76
77 asm("lgdt %0;"
78 : : "m" (descr));
79}
80
81// returns the selector type of a given id
82selector_type i386_selector_get( selector_id id )
83{
84 return gdt_table[id/8];
85}