The compiler can get confused when referencing a C function in a different mode. (It reasonably assumes that the C function in the current mode is desired.) To avoid this compiler confusion, introduce symbol prefixes (_cfunc16_, _cfunc32flat_, _cfunc32seg_) that must be used on C function symbols that are referenced from other compilation modes.
This makes it less likely compiler confusion will occur. It will also makes it easier to implement and use vtable like operation structures. --- src/pci.c | 12 ++++-------- src/resume.c | 2 +- src/romlayout.S | 12 ++++++------ src/stacks.c | 6 ++---- src/types.h | 12 ++++++------ tools/layoutrom.py | 39 ++++++++++++++++++++++++++++----------- 6 files changed, 47 insertions(+), 36 deletions(-)
diff --git a/src/pci.c b/src/pci.c index e43c83a..5237f19 100644 --- a/src/pci.c +++ b/src/pci.c @@ -229,21 +229,19 @@ pci_reboot(void)
// helper functions to access pci mmio bars from real mode
-extern u32 pci_readl_32(u32 addr); -#if MODESEGMENT == 0 u32 VISIBLE32FLAT pci_readl_32(u32 addr) { dprintf(3, "32: pci read : %x\n", addr); return readl((void*)addr); } -#endif
u32 pci_readl(u32 addr) { if (MODESEGMENT) { dprintf(3, "16: pci read : %x\n", addr); - return call32(pci_readl_32, addr, -1); + extern void _cfunc32flat_pci_readl_32(u32 addr); + return call32(_cfunc32flat_pci_readl_32, addr, -1); } else { return pci_readl_32(addr); } @@ -254,15 +252,12 @@ struct reg32 { u32 data; };
-extern void pci_writel_32(struct reg32 *reg32); -#if MODESEGMENT == 0 void VISIBLE32FLAT pci_writel_32(struct reg32 *reg32) { dprintf(3, "32: pci write: %x, %x (%p)\n", reg32->addr, reg32->data, reg32); writel((void*)(reg32->addr), reg32->data); } -#endif
void pci_writel(u32 addr, u32 val) { @@ -271,7 +266,8 @@ void pci_writel(u32 addr, u32 val) dprintf(3, "16: pci write: %x, %x (%x:%p)\n", reg32.addr, reg32.data, GET_SEG(SS), ®32); void *flatptr = MAKE_FLATPTR(GET_SEG(SS), ®32); - call32(pci_writel_32, (u32)flatptr, -1); + extern void _cfunc32flat_pci_writel_32(struct reg32 *reg32); + call32(_cfunc32flat_pci_writel_32, (u32)flatptr, -1); } else { pci_writel_32(®32); } diff --git a/src/resume.c b/src/resume.c index 2a743c9..20e2e3d 100644 --- a/src/resume.c +++ b/src/resume.c @@ -40,7 +40,7 @@ handle_resume(u8 status) asm volatile( "movw %w1, %%ss\n" "movl %0, %%esp\n" - "movl $s3_resume, %%edx\n" + "movl $_cfunc32flat_s3_resume, %%edx\n" "jmp transition32\n" : : "i"(BUILD_S3RESUME_STACK_ADDR), "r"(0) ); diff --git a/src/romlayout.S b/src/romlayout.S index d83f337..7a14a7f 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -252,7 +252,7 @@ entry_post: jnz 1f
// Normal entry point - ENTRY_INTO32 _start + ENTRY_INTO32 _cfunc32flat__start
// Entry point when a post call looks like a resume. 1: @@ -367,7 +367,7 @@ apm32protected_entry: pushl %cs // Move second descriptor after %cs to %gs addl $16, (%esp) popl %gs - ENTRY_ARG_ESP handle_apm32 + ENTRY_ARG_ESP _cfunc32seg_handle_apm32 popl %gs popfl lretl @@ -379,7 +379,7 @@ pcibios32_entry: pushl %gs // Backup %gs and set %gs=%ds pushl %ds popl %gs - ENTRY_ARG_ESP handle_pcibios32 + ENTRY_ARG_ESP _cfunc32seg_handle_pcibios32 popl %gs popfl lretl @@ -418,7 +418,7 @@ post32: movw %ax, %gs movw %ax, %ss movl $BUILD_STACK_ADDR, %esp - ljmpl $SEG32_MODE32_CS, $_start + ljmpl $SEG32_MODE32_CS, $_cfunc32flat__start
.code16gcc
@@ -476,11 +476,11 @@ irqentryarg: // int 18/19 are special - they reset stack and call into 32bit mode. DECLFUNC entry_19 entry_19: - ENTRY_INTO32 handle_19 + ENTRY_INTO32 _cfunc32flat_handle_19
DECLFUNC entry_18 entry_18: - ENTRY_INTO32 handle_18 + ENTRY_INTO32 _cfunc32flat_handle_18
/**************************************************************** diff --git a/src/stacks.c b/src/stacks.c index c77ba1f..53bf669 100644 --- a/src/stacks.c +++ b/src/stacks.c @@ -373,8 +373,6 @@ wait_preempt(void) return 1; }
-extern void yield_preempt(void); -#if MODESEGMENT == 0 // Try to execute 32bit threads. void VISIBLE32INIT yield_preempt(void) @@ -382,7 +380,6 @@ yield_preempt(void) PreemptCount++; switch_next(&MainThread); } -#endif
// 16bit code that checks if threads are pending and executes them if so. void @@ -393,5 +390,6 @@ check_preempt(void) || GET_FLATPTR(MainThread.next) == &MainThread) return;
- call32(yield_preempt, 0, 0); + extern void _cfunc32flat_yield_preempt(void); + call32(_cfunc32flat_yield_preempt, 0, 0); } diff --git a/src/types.h b/src/types.h index 7d610ec..c0c6d26 100644 --- a/src/types.h +++ b/src/types.h @@ -44,11 +44,11 @@ extern void __force_link_error__only_in_16bit(void) __noreturn; // Notes a function as externally visible in the 16bit code chunk. # define VISIBLE16 __VISIBLE // Notes a function as externally visible in the 32bit flat code chunk. -# define VISIBLE32FLAT __section(".discard.func32flat." UNIQSEC) noinline __weak +# define VISIBLE32FLAT __section(".discard.func32flat." UNIQSEC) noinline // Notes a 32bit flat function that will only be called during init. # define VISIBLE32INIT VISIBLE32FLAT // Notes a function as externally visible in the 32bit segmented code chunk. -# define VISIBLE32SEG __section(".discard.func32seg." UNIQSEC) noinline __weak +# define VISIBLE32SEG __section(".discard.func32seg." UNIQSEC) noinline // Designate a variable as (only) visible to 16bit code. # define VAR16 __section(".data16." UNIQSEC) // Designate a variable as visible to 16bit, 32bit, and assembler code. @@ -70,8 +70,8 @@ extern void __force_link_error__only_in_16bit(void) __noreturn; # define ASSERT32SEG() __force_link_error__only_in_32bit_segmented() # define ASSERT32FLAT() __force_link_error__only_in_32bit_flat() #elif MODESEGMENT == 1 -# define VISIBLE16 __section(".discard.func16." UNIQSEC) noinline __weak -# define VISIBLE32FLAT __section(".discard.func32flat." UNIQSEC) noinline __weak +# define VISIBLE16 __section(".discard.func16." UNIQSEC) noinline +# define VISIBLE32FLAT __section(".discard.func32flat." UNIQSEC) noinline # define VISIBLE32INIT VISIBLE32FLAT # define VISIBLE32SEG __VISIBLE # define VAR16 __section(".discard.var16." UNIQSEC) @@ -86,10 +86,10 @@ extern void __force_link_error__only_in_16bit(void) __noreturn; # define ASSERT32SEG() do { } while (0) # define ASSERT32FLAT() __force_link_error__only_in_32bit_flat() #else -# define VISIBLE16 __section(".discard.func16." UNIQSEC) noinline __weak +# define VISIBLE16 __section(".discard.func16." UNIQSEC) noinline # define VISIBLE32FLAT __section(".text.runtime." UNIQSEC) __VISIBLE # define VISIBLE32INIT __section(".text.init." UNIQSEC) __VISIBLE -# define VISIBLE32SEG __section(".discard.func32seg." UNIQSEC) noinline __weak +# define VISIBLE32SEG __section(".discard.func32seg." UNIQSEC) noinline # define VAR16 __section(".discard.var16." UNIQSEC) # define VAR16VISIBLE VAR16 __VISIBLE __weak # define VAR16EXPORT VAR16VISIBLE diff --git a/tools/layoutrom.py b/tools/layoutrom.py index 7eca502..4109b16 100755 --- a/tools/layoutrom.py +++ b/tools/layoutrom.py @@ -209,15 +209,16 @@ def outXRefs(sections): for reloc in section.relocs: symbol = reloc.symbol if (symbol.section is None - or symbol.section.fileid == section.fileid - or symbol.name in xrefs): + or (symbol.section.fileid == section.fileid + and symbol.name == reloc.symbolname) + or reloc.symbolname in xrefs): continue - xrefs[symbol.name] = 1 + xrefs[reloc.symbolname] = 1 addr = symbol.section.finalloc + symbol.offset if (section.fileid == '32flat' and symbol.section.fileid in ('16', '32seg')): addr += BUILD_BIOS_ADDR - out += "%s = 0x%x ;\n" % (symbol.name, addr) + out += "%s = 0x%x ;\n" % (reloc.symbolname, addr) return out
# Write LD script includes for the given sections using relative offsets @@ -396,13 +397,29 @@ def findInit(sections): # Section garbage collection ######################################################################
+CFUNCPREFIX = [('_cfunc16_', 0), ('_cfunc32seg_', 1), ('_cfunc32flat_', 2)] + # Find and keep the section associated with a symbol (if available). -def keepsymbol(reloc, infos, pos): - symbolname = reloc.symbol.name +def keepsymbol(reloc, infos, pos, isxref): + symbolname = reloc.symbolname + mustbecfunc = 0 + for symprefix, needpos in CFUNCPREFIX: + if symbolname.startswith(symprefix): + if needpos != pos: + return -1 + symbolname = symbolname[len(symprefix):] + mustbecfunc = 1 + break symbol = infos[pos][1].get(symbolname) if (symbol is None or symbol.section is None or symbol.section.name.startswith('.discard.')): return -1 + isdestcfunc = (symbol.section.name.startswith('.text.') + and not symbol.section.name.startswith('.text.asm.')) + if ((mustbecfunc and not isdestcfunc) + or (not mustbecfunc and isdestcfunc and isxref)): + return -1 + reloc.symbol = symbol keepsection(symbol.section, infos, pos) return 0 @@ -416,14 +433,14 @@ def keepsection(section, infos, pos=0): section.keep = 1 # Keep all sections that this section points to for reloc in section.relocs: - ret = keepsymbol(reloc, infos, pos) + ret = keepsymbol(reloc, infos, pos, 0) if not ret: continue # Not in primary sections - it may be a cross 16/32 reference - ret = keepsymbol(reloc, infos, (pos+1)%3) + ret = keepsymbol(reloc, infos, (pos+1)%3, 1) if not ret: continue - ret = keepsymbol(reloc, infos, (pos+2)%3) + ret = keepsymbol(reloc, infos, (pos+2)%3, 1) if not ret: continue
@@ -449,7 +466,7 @@ class Section: name = size = alignment = fileid = relocs = None finalloc = category = keep = None class Reloc: - offset = type = symbol = None + offset = type = symbolname = symbol = None class Symbol: name = offset = section = None
@@ -514,6 +531,7 @@ def parseObjDump(file, fileid): reloc = Reloc() reloc.offset = int(off, 16) reloc.type = type + reloc.symbolname = symbolname reloc.symbol = symbols[symbolname] relocsection.relocs.append(reloc) except ValueError: @@ -541,7 +559,6 @@ def main(): findInit(sections)
# Determine the final memory locations of each kept section. - # locsX = [(addr, sectioninfo), ...] doLayout(sections)
# Write out linker script files.