Changeset 74d2d940 in rtems
- Timestamp:
- 11/20/14 14:00:30 (9 years ago)
- Branches:
- 4.11, 5, master
- Children:
- 586c86c7
- Parents:
- b2db1f5c
- git-author:
- Jan Dolezal <dolezj21@…> (11/20/14 14:00:30)
- git-committer:
- Gedare Bloom <gedare@…> (11/20/14 14:52:39)
- Location:
- c/src/lib
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/lib/libbsp/i386/shared/irq/idt.c
rb2db1f5c r74d2d940 230 230 } 231 231 232 /* 233 * Caution this function assumes the GDTR has been already set. 234 */ 235 int i386_set_gdt_entry (unsigned short segment_selector, unsigned base, 236 unsigned limit) 237 { 238 unsigned gdt_limit; 239 unsigned short tmp_segment = 0; 240 unsigned int limit_adjusted; 241 segment_descriptors* gdt_entry_tbl; 232 uint32_t i386_raw_gdt_entry (uint16_t segment_selector_index, 233 segment_descriptors* sd) 234 { 235 uint16_t gdt_limit; 236 uint16_t tmp_segment = 0; 237 segment_descriptors* gdt_entry_tbl; 238 uint8_t present; 242 239 243 240 i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit); 244 241 245 if (segment_selector > limit) { 246 return 0; 247 } 248 /* 249 * set up limit first 250 */ 251 limit_adjusted = limit; 252 if ( limit > 4095 ) { 253 gdt_entry_tbl[segment_selector].granularity = 1; 254 limit_adjusted /= 4096; 255 } 256 gdt_entry_tbl[segment_selector].limit_15_0 = limit_adjusted & 0xffff; 257 gdt_entry_tbl[segment_selector].limit_19_16 = (limit_adjusted >> 16) & 0xf; 258 /* 259 * set up base 260 */ 261 gdt_entry_tbl[segment_selector].base_address_15_0 = base & 0xffff; 262 gdt_entry_tbl[segment_selector].base_address_23_16 = (base >> 16) & 0xff; 263 gdt_entry_tbl[segment_selector].base_address_31_24 = (base >> 24) & 0xff; 264 /* 265 * set up descriptor type (this may well becomes a parameter if needed) 266 */ 267 gdt_entry_tbl[segment_selector].type = 2; /* Data R/W */ 268 gdt_entry_tbl[segment_selector].descriptor_type = 1; /* Code or Data */ 269 gdt_entry_tbl[segment_selector].privilege = 0; /* ring 0 */ 270 gdt_entry_tbl[segment_selector].present = 1; /* not present */ 271 272 /* 273 * Now, reload all segment registers so the limit takes effect. 274 */ 275 242 if (segment_selector_index >= (gdt_limit+1)/8) { 243 /* index to GDT table out of bounds */ 244 return 0; 245 } 246 if (segment_selector_index == 0) { 247 /* index 0 is not usable */ 248 return 0; 249 } 250 251 /* put prepared descriptor into the GDT */ 252 present = sd->present; 253 sd->present = 0; 254 gdt_entry_tbl[segment_selector_index].present = 0; 255 RTEMS_COMPILER_MEMORY_BARRIER(); 256 gdt_entry_tbl[segment_selector_index] = *sd; 257 RTEMS_COMPILER_MEMORY_BARRIER(); 258 gdt_entry_tbl[segment_selector_index].present = present; 259 sd->present = present; 260 /* 261 * Now, reload all segment registers so that the possible changes takes effect. 262 */ 276 263 __asm__ volatile( "movw %%ds,%0 ; movw %0,%%ds\n\t" 277 264 "movw %%es,%0 ; movw %0,%%es\n\t" … … 281 268 : "=r" (tmp_segment) 282 269 : "0" (tmp_segment) 283 ); 284 285 return 1; 286 } 270 ); 271 return 1; 272 } 273 274 void i386_fill_segment_desc_base(uint32_t base, 275 segment_descriptors* sd) 276 { 277 sd->base_address_15_0 = base & 0xffff; 278 sd->base_address_23_16 = (base >> 16) & 0xff; 279 sd->base_address_31_24 = (base >> 24) & 0xff; 280 } 281 282 void i386_fill_segment_desc_limit(uint32_t limit, 283 segment_descriptors* sd) 284 { 285 sd->granularity = 0; 286 if (limit > 65535) { 287 sd->granularity = 1; 288 limit /= 4096; 289 } 290 sd->limit_15_0 = limit & 0xffff; 291 sd->limit_19_16 = (limit >> 16) & 0xf; 292 } 293 294 /* 295 * Caution this function assumes the GDTR has been already set. 296 */ 297 uint32_t i386_set_gdt_entry (uint16_t segment_selector_index, uint32_t base, 298 uint32_t limit) 299 { 300 segment_descriptors gdt_entry; 301 memset(&gdt_entry, 0, sizeof(gdt_entry)); 302 303 i386_fill_segment_desc_limit(limit, &gdt_entry); 304 i386_fill_segment_desc_base(base, &gdt_entry); 305 /* 306 * set up descriptor type (this may well becomes a parameter if needed) 307 */ 308 gdt_entry.type = 2; /* Data R/W */ 309 gdt_entry.descriptor_type = 1; /* Code or Data */ 310 gdt_entry.privilege = 0; /* ring 0 */ 311 gdt_entry.present = 1; /* not present */ 312 313 /* 314 * Now, reload all segment registers so the limit takes effect. 315 */ 316 return i386_raw_gdt_entry(segment_selector_index, &gdt_entry); 317 } 318 319 uint16_t i386_next_empty_gdt_entry () 320 { 321 uint16_t gdt_limit; 322 segment_descriptors* gdt_entry_tbl; 323 /* initial amount of filled descriptors */ 324 static uint16_t segment_selector_index = 2; 325 326 segment_selector_index += 1; 327 i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit); 328 if (segment_selector_index >= (gdt_limit+1)/8) { 329 return 0; 330 } 331 return segment_selector_index; 332 } 333 334 uint16_t i386_cpy_gdt_entry(uint16_t segment_selector_index, 335 segment_descriptors* struct_to_fill) 336 { 337 uint16_t gdt_limit; 338 segment_descriptors* gdt_entry_tbl; 339 340 i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit); 341 342 if (segment_selector_index >= (gdt_limit+1)/8) { 343 return 0; 344 } 345 346 *struct_to_fill = gdt_entry_tbl[segment_selector_index]; 347 return segment_selector_index; 348 } 349 350 segment_descriptors* i386_get_gdt_entry(uint16_t segment_selector_index) 351 { 352 uint16_t gdt_limit; 353 segment_descriptors* gdt_entry_tbl; 354 355 i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit); 356 357 if (segment_selector_index >= (gdt_limit+1)/8) { 358 return 0; 359 } 360 return &gdt_entry_tbl[segment_selector_index]; 361 } 362 363 uint32_t i386_limit_gdt_entry(segment_descriptors* gdt_entry) 364 { 365 uint32_t lim = (gdt_entry->limit_15_0 + (gdt_entry->limit_19_16<<16)); 366 if (gdt_entry->granularity) { 367 return lim*4096+4095; 368 } 369 return lim; 370 } -
c/src/lib/libcpu/i386/cpu.h
rb2db1f5c r74d2d940 29 29 #include <rtems/score/interrupts.h> 30 30 31 #include < stdint.h>31 #include <rtems/score/basedefs.h> 32 32 33 33 /* … … 257 257 unsigned int granularity : 1; 258 258 unsigned int base_address_31_24 : 8; 259 } segment_descriptors;259 } RTEMS_COMPILER_PACKED_ATTRIBUTE segment_descriptors; 260 260 261 261 /* … … 272 272 uint16_t limit); 273 273 274 /** 275 * C callable function: 276 * Puts global descriptor @sd to the global descriptor table on index 277 * @segment_selector_index 278 * 279 * @retval 0 FAILED out of GDT range or index is 0, which is not valid 280 * index in GDT 281 * 1 SUCCESS 282 */ 283 extern uint32_t i386_raw_gdt_entry (uint16_t segment_selector_index, 284 segment_descriptors* sd); 285 286 /** 287 * C callable function 288 * fills @sd with provided @base in appropriate fields of @sd 289 * 290 * @param base 32-bit address to be set as descriptor's base 291 * @param sd descriptor being filled with @base 292 */ 293 extern void i386_fill_segment_desc_base (uint32_t base, 294 segment_descriptors* sd); 295 296 /** 297 * C callable function 298 * fills @sd with provided @limit in appropriate fields of @sd 299 * also influences granularity bit 300 * 301 * @param limit 32-bit value representing number of limit bytes 302 * @param sd descriptor being filled with @limit 303 */ 304 extern void i386_fill_segment_desc_limit (uint32_t limit, 305 segment_descriptors* sd); 306 274 307 /* 275 308 * C callable function enabling to set up one raw interrupt handler 276 309 */ 277 extern int i386_set_gdt_entry (unsigned short segment_selector, unsigned base, 278 unsigned limit); 310 extern uint32_t i386_set_gdt_entry (uint16_t segment_selector, 311 uint32_t base, 312 uint32_t limit); 313 314 /** 315 * C callable function returns next empty descriptor in GDT. 316 * 317 * @retval 0 FAILED GDT is full 318 * <1;65535> segment_selector number as index to GDT 319 */ 320 extern uint16_t i386_next_empty_gdt_entry (void); 321 322 /** 323 * Copies GDT entry at index @segment_selector to structure 324 * pointed to by @struct_to_fill 325 * 326 * @param segment_selector index to GDT table for specifying descriptor to copy 327 * @retval 0 FAILED segment_selector out of GDT range 328 * <1;65535> retrieved segment_selector 329 */ 330 extern uint16_t i386_cpy_gdt_entry (uint16_t segment_selector, 331 segment_descriptors* struct_to_fill); 332 333 /** 334 * Returns pointer to GDT table at index given by @segment_selector 335 * 336 * @param segment_selector index to GDT table for specifying descriptor to get 337 * @retval NULL FAILED segment_selector out of GDT range 338 * pointer to GDT table at @segment_selector 339 */ 340 extern segment_descriptors* i386_get_gdt_entry (uint16_t sgmnt_selector); 341 342 /** 343 * Extracts base address from GDT entry pointed to by @gdt_entry 344 * 345 * @param gdt_entry pointer to entry from which base should be retrieved 346 * @retval base address from GDT entry 347 */ 348 RTEMS_INLINE_ROUTINE void* i386_base_gdt_entry (segment_descriptors* gdt_entry) 349 { 350 return (void*)(gdt_entry->base_address_15_0 | 351 (gdt_entry->base_address_23_16<<16) | 352 (gdt_entry->base_address_31_24<<24)); 353 } 354 355 /** 356 * Extracts limit in bytes from GDT entry pointed to by @gdt_entry 357 * 358 * @param gdt_entry pointer to entry from which limit should be retrieved 359 * @retval limit value in bytes from GDT entry 360 */ 361 extern uint32_t i386_limit_gdt_entry (segment_descriptors* gdt_entry); 279 362 280 363 /*
Note: See TracChangeset
for help on using the changeset viewer.