Skip to content

Commit b8a81de

Browse files
rizlikdanielinux
authored andcommitted
x86: add wrapper to run 32bit code in 64bit long mode
1 parent 6358153 commit b8a81de

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

include/x86/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,5 @@ int cpuid_is_1gb_page_supported();
6868
void switch_to_long_mode(uint64_t *entry, uint32_t page_table);
6969
void x86_log_memory_load(uint32_t start, uint32_t end, const char *name);
7070
void hlt();
71+
int x86_run_fsp_32bit(void* api, void* arg);
7172
#endif /* COMMON_H */

src/x86/common.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <stdint.h>
3636

3737
#include <x86/common.h>
38+
#include <x86/gdt.h>
3839

3940
#define barrier() __asm__ __volatile__ ("":::"memory");
4041

@@ -371,4 +372,89 @@ void x86_log_memory_load(uint32_t start, uint32_t end, const char *name)
371372
{
372373
wolfBoot_printf("mem: [ 0x%x, 0x%x ] - %s (0x%x) \n\r", start, end, name, end - start);
373374
}
375+
376+
#if !defined(BUILD_LOADER_STAGE1)
377+
int x86_run_fsp_32bit(void* api, void* arg)
378+
{
379+
uint32_t status;
380+
__asm__ volatile (
381+
/* arg on the stack, will be used as arg */
382+
"mov %[arg], %%rax\n"
383+
"shl $32, %%rax\n"
384+
"or %[api], %%rax\n"
385+
"push %%rax\n"
386+
"push %[SEG_COMP]\n"
387+
"lea (1f), %%rax\n"
388+
"push %%rax\n"
389+
"retfq\n"
390+
"1:\n"
391+
/* we are now in compatibility mode */
392+
".code32\n"
393+
/* disable paging */
394+
"mov %%cr0, %%eax\n"
395+
"mov %[PG], %%edx\n"
396+
"not %%edx\n"
397+
"and %%edx, %%eax\n"
398+
"mov %%eax, %%cr0\n"
399+
/* disable EFER.LME */
400+
"mov $0xc0000080, %%ecx\n"
401+
"rdmsr\n"
402+
"mov %[LME], %%ecx\n"
403+
"not %%ecx\n"
404+
"and %%ecx, %%eax\n"
405+
"mov $0xc0000080, %%ecx\n"
406+
"wrmsr\n"
407+
/* disable PAE */
408+
"mov %%cr4, %%eax\n"
409+
"mov %[PAE], %%edx\n"
410+
"not %%edx\n"
411+
"and %%edx, %%eax\n"
412+
"mov %%eax, %%cr4\n"
413+
/* get api from stack */
414+
"pop %%eax\n"
415+
"call *%%eax\n"
416+
/* remove parameter from the stack */
417+
"add $4, %%esp\n"
418+
/* save status to ebx */
419+
"mov %%eax, %%ebx\n"
420+
/* enable PAE */
421+
"mov %%cr4, %%eax\n"
422+
"or %[PAE], %%eax\n"
423+
"mov %%eax, %%cr4\n"
424+
/* enable EFER_LME */
425+
"mov $0xc0000080, %%ecx\n"
426+
"rdmsr\n"
427+
"or %[LME], %%eax\n"
428+
"mov $0xc0000080, %%ecx\n"
429+
"wrmsr\n"
430+
/* setup far pointer on the stack */
431+
"push %[SEG_LONG]\n"
432+
"push $2f\n"
433+
/* enable paging */
434+
"mov %%cr0, %%eax\n"
435+
"or %[PG], %%eax\n"
436+
"mov %%eax, %%cr0\n"
437+
"retf\n"
438+
"2:\n"
439+
/* back in long mode */
440+
".code64\n"
441+
/* save status */
442+
"mov %%ebx, %[status]\n"
443+
:[status]"=m"(status)
444+
:[SEG_COMP]"i"(GDT_CS_32BIT_COMPAT),
445+
[SEG_LONG]"i"(GDT_CS_64BIT),
446+
[PG]"i"(CR0_PG_BIT),
447+
[LME]"i"(IA32_EFER_LME),
448+
[PAE]"i"(CR4_PAE_BIT),
449+
[api]"r"(api),
450+
[arg]"r"(arg)
451+
: "rax", "rbx", "rcx", "rdx");
452+
return status;
453+
}
454+
#else
455+
int x86_run_fsp_32bit(void* api, void* arg)
456+
{
457+
return 0;
458+
}
459+
#endif /* !STAGE1 */
374460
#endif /* COMMON_H_ */

0 commit comments

Comments
 (0)