|
|
1.1 ! root 1: /* Segmentation of the AMD64 architecture. ! 2: * ! 3: * 2003-07 by SONE Takeshi ! 4: */ ! 5: ! 6: #include "config.h" ! 7: #include "kernel/kernel.h" ! 8: #include "libopenbios/sys_info.h" ! 9: #include "relocate.h" ! 10: #include "segment.h" ! 11: ! 12: #define printf printk ! 13: #ifdef CONFIG_DEBUG_BOOT ! 14: #define debug printk ! 15: #else ! 16: #define debug(x...) ! 17: #endif ! 18: ! 19: /* i386 lgdt argument */ ! 20: struct gdtarg { ! 21: unsigned short limit; ! 22: unsigned int base; ! 23: } __attribute__((packed)); ! 24: ! 25: /* How far the virtual address (used in C) is different from physical ! 26: * address. Since we start in flat mode, the initial value is zero. */ ! 27: unsigned long virt_offset = 0; ! 28: ! 29: /* GDT, the global descriptor table */ ! 30: struct segment_desc gdt[NUM_SEG] = { ! 31: /* 0x00: null segment */ ! 32: {0, 0, 0, 0, 0, 0}, ! 33: /* 0x08: flat code segment */ ! 34: {0xffff, 0, 0, 0x9f, 0xcf, 0}, ! 35: /* 0x10: flat data segment */ ! 36: {0xffff, 0, 0, 0x93, 0xcf, 0}, ! 37: /* 0x18: code segment for relocated execution */ ! 38: {0xffff, 0, 0, 0x9f, 0xcf, 0}, ! 39: /* 0x20: data segment for relocated execution */ ! 40: {0xffff, 0, 0, 0x93, 0xcf, 0}, ! 41: }; ! 42: ! 43: extern char _start[], _end[]; ! 44: ! 45: void relocate(struct sys_info *info) ! 46: { ! 47: int i; ! 48: unsigned long prog_addr; ! 49: unsigned long prog_size; ! 50: unsigned long addr, new_base; ! 51: unsigned long long segsize; ! 52: unsigned long new_offset; ! 53: unsigned d0, d1, d2; ! 54: struct gdtarg gdtarg; ! 55: #define ALIGNMENT 16 ! 56: ! 57: prog_addr = virt_to_phys(&_start); ! 58: prog_size = virt_to_phys(&_end) - virt_to_phys(&_start); ! 59: debug("Current location: %#lx-%#lx\n", prog_addr, prog_addr+prog_size-1); ! 60: ! 61: new_base = 0; ! 62: for (i = 0; i < info->n_memranges; i++) { ! 63: if (info->memrange[i].base >= 1ULL<<32) ! 64: continue; ! 65: segsize = info->memrange[i].size; ! 66: if (info->memrange[i].base + segsize > 1ULL<<32) ! 67: segsize = (1ULL<<32) - info->memrange[i].base; ! 68: if (segsize < prog_size+ALIGNMENT) ! 69: continue; ! 70: addr = info->memrange[i].base + segsize - prog_size; ! 71: addr &= ~(ALIGNMENT-1); ! 72: if (addr >= prog_addr && addr < prog_addr + prog_size) ! 73: continue; ! 74: if (prog_addr >= addr && prog_addr < addr + prog_size) ! 75: continue; ! 76: if (addr > new_base) ! 77: new_base = addr; ! 78: } ! 79: if (new_base == 0) { ! 80: printf("Can't find address to relocate\n"); ! 81: return; ! 82: } ! 83: ! 84: debug("Relocating to %#lx-%#lx... ", ! 85: new_base, new_base + prog_size - 1); ! 86: ! 87: /* New virtual address offset */ ! 88: new_offset = new_base - (unsigned long) &_start; ! 89: ! 90: /* Tweak the GDT */ ! 91: gdt[RELOC_CODE].base_0 = (unsigned short) new_offset; ! 92: gdt[RELOC_CODE].base_16 = (unsigned char) (new_offset>>16); ! 93: gdt[RELOC_CODE].base_24 = (unsigned char) (new_offset>>24); ! 94: gdt[RELOC_DATA].base_0 = (unsigned short) new_offset; ! 95: gdt[RELOC_DATA].base_16 = (unsigned char) (new_offset>>16); ! 96: gdt[RELOC_DATA].base_24 = (unsigned char) (new_offset>>24); ! 97: ! 98: /* Load new GDT and reload segments */ ! 99: gdtarg.base = new_offset + (unsigned long) gdt; ! 100: gdtarg.limit = GDT_LIMIT; ! 101: __asm__ __volatile__ ( ! 102: "rep; movsb\n\t" /* copy everything */ ! 103: "lgdt %3\n\t" ! 104: "ljmp %4, $1f\n1:\t" ! 105: "movw %5, %%ds\n\t" ! 106: "movw %5, %%es\n\t" ! 107: "movw %5, %%fs\n\t" ! 108: "movw %5, %%gs\n\t" ! 109: "movw %5, %%ss\n" ! 110: : "=&S" (d0), "=&D" (d1), "=&c" (d2) ! 111: : "m" (gdtarg), "n" (RELOC_CS), "q" ((unsigned short) RELOC_DS), ! 112: "0" (&_start), "1" (new_base), "2" (prog_size)); ! 113: ! 114: virt_offset = new_offset; ! 115: debug("ok\n"); ! 116: } ! 117: ! 118: #if 0 ! 119: /* Copy GDT to new location and reload it */ ! 120: void move_gdt(unsigned long newgdt) ! 121: { ! 122: struct gdtarg gdtarg; ! 123: ! 124: debug("Moving GDT to %#lx...", newgdt); ! 125: memcpy(phys_to_virt(newgdt), gdt, sizeof gdt); ! 126: gdtarg.base = newgdt; ! 127: gdtarg.limit = GDT_LIMIT; ! 128: debug("reloading GDT..."); ! 129: __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg)); ! 130: debug("reloading CS for fun..."); ! 131: __asm__ __volatile__ ("ljmp %0, $1f\n1:" : : "n" (RELOC_CS)); ! 132: debug("ok\n"); ! 133: } ! 134: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.