|
|
1.1 root 1: /* tag: x86 context switching
2: *
3: * 2003-10 by SONE Takeshi
4: *
5: * See the file "COPYING" for further information about
6: * the copyright and warranty status of this work.
7: */
8:
9: #include "config.h"
10: #include "kernel/kernel.h"
11: #include "segment.h"
12: #include "context.h"
13: #include "libopenbios/sys_info.h"
14: #include "boot.h"
15: #include "openbios.h"
16:
17: #define MAIN_STACK_SIZE 16384
18: #define IMAGE_STACK_SIZE 4096
19:
20: #define debug printk
21:
22: static void start_main(void); /* forward decl. */
23: void __exit_context(void); /* assembly routine */
24:
25: /*
26: * Main context structure
27: * It is placed at the bottom of our stack, and loaded by assembly routine
28: * to start us up.
29: */
30: static struct context main_ctx __attribute__((section (".initctx"))) = {
31: .gdt_base = (uint32_t) gdt,
32: .gdt_limit = GDT_LIMIT,
33: .cs = FLAT_CS,
34: .ds = FLAT_DS,
35: .es = FLAT_DS,
36: .fs = FLAT_DS,
37: .gs = FLAT_DS,
38: .ss = FLAT_DS,
39: .esp = (uint32_t) ESP_LOC(&main_ctx),
40: .eip = (uint32_t) start_main,
41: .return_addr = (uint32_t) __exit_context,
42: };
43:
44: /* This is used by assembly routine to load/store the context which
45: * it is to switch/switched. */
46: struct context *__context = &main_ctx;
47:
48: /* Stack for loaded ELF image */
49: static uint8_t image_stack[IMAGE_STACK_SIZE];
50:
51: /* Pointer to startup context (physical address) */
52: unsigned long __boot_ctx;
53:
54: /*
55: * Main starter
56: * This is the C function that runs first.
57: */
58: static void start_main(void)
59: {
60: int retval;
61:
62: /* Save startup context, so we can refer to it later.
63: * We have to keep it in physical address since we will relocate. */
64: __boot_ctx = virt_to_phys(__context);
65:
66: init_exceptions();
67: /* Start the real fun */
68: retval = openbios();
69:
70: /* Pass return value to startup context. Bootloader may see it. */
71: boot_ctx->eax = retval;
72:
73: /* Returning from here should jump to __exit_context */
74: __context = boot_ctx;
75: }
76:
77: /* Setup a new context using the given stack.
78: */
79: struct context *
80: init_context(uint8_t *stack, uint32_t stack_size, int num_params)
81: {
82: struct context *ctx;
83:
84: ctx = (struct context *)
85: (stack + stack_size - (sizeof(*ctx) + num_params*sizeof(uint32_t)));
86: memset(ctx, 0, sizeof(*ctx));
87:
88: /* Fill in reasonable default for flat memory model */
89: ctx->gdt_base = virt_to_phys(gdt);
90: ctx->gdt_limit = GDT_LIMIT;
91: ctx->cs = FLAT_CS;
92: ctx->ds = FLAT_DS;
93: ctx->es = FLAT_DS;
94: ctx->fs = FLAT_DS;
95: ctx->gs = FLAT_DS;
96: ctx->ss = FLAT_DS;
97: ctx->esp = virt_to_phys(ESP_LOC(ctx));
98: ctx->return_addr = virt_to_phys(__exit_context);
99:
100: return ctx;
101: }
102:
103: /* Switch to another context. */
104: struct context *switch_to(struct context *ctx)
105: {
106: struct context *save, *ret;
107:
108: debug("switching to new context:\n");
109: save = __context;
110: __context = ctx;
111: asm ("pushl %cs; call __switch_context");
112: ret = __context;
113: __context = save;
114: return ret;
115: }
116:
117: /* Start ELF Boot image */
118: unsigned int start_elf(unsigned long entry_point, unsigned long param)
119: {
120: struct context *ctx;
121:
122: ctx = init_context(image_stack, sizeof image_stack, 1);
123: ctx->eip = entry_point;
124: ctx->param[0] = param;
125: ctx->eax = 0xe1fb007;
126: ctx->ebx = param;
127:
128: ctx = switch_to(ctx);
129: return ctx->eax;
130: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.