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.
// helper functions to access pci mmio bars from real mode
// 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);
}
u32 VISIBLE32FLAT
pci_readl_32(u32 addr)
{
dprintf(3, "32: pci read : %x\n", addr);
return readl((void*)addr);
}
u32 pci_readl(u32 addr)
{
if (MODESEGMENT) {
dprintf(3, "16: pci read : %x\n", addr);
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);
}
} else {
return pci_readl_32(addr);
}
-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);
}
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);
}
void pci_writel(u32 addr, u32 val)
{
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);
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);
}
} else {
pci_writel_32(®32);
}
asm volatile(
"movw %w1, %%ss\n"
"movl %0, %%esp\n"
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)
);
"jmp transition32\n"
: : "i"(BUILD_S3RESUME_STACK_ADDR), "r"(0)
);
jnz 1f
// Normal entry point
jnz 1f
// Normal entry point
+ ENTRY_INTO32 _cfunc32flat__start
// Entry point when a post call looks like a resume.
1:
// Entry point when a post call looks like a resume.
1:
pushl %cs // Move second descriptor after %cs to %gs
addl $16, (%esp)
popl %gs
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
pushl %gs // Backup %gs and set %gs=%ds
pushl %ds
popl %gs
pushl %gs // Backup %gs and set %gs=%ds
pushl %ds
popl %gs
- ENTRY_ARG_ESP handle_pcibios32
+ ENTRY_ARG_ESP _cfunc32seg_handle_pcibios32
movw %ax, %gs
movw %ax, %ss
movl $BUILD_STACK_ADDR, %esp
movw %ax, %gs
movw %ax, %ss
movl $BUILD_STACK_ADDR, %esp
- ljmpl $SEG32_MODE32_CS, $_start
+ ljmpl $SEG32_MODE32_CS, $_cfunc32flat__start
// int 18/19 are special - they reset stack and call into 32bit mode.
DECLFUNC entry_19
entry_19:
// int 18/19 are special - they reset stack and call into 32bit mode.
DECLFUNC entry_19
entry_19:
+ ENTRY_INTO32 _cfunc32flat_handle_19
DECLFUNC entry_18
entry_18:
DECLFUNC entry_18
entry_18:
+ ENTRY_INTO32 _cfunc32flat_handle_18
/****************************************************************
/****************************************************************
-extern void yield_preempt(void);
-#if MODESEGMENT == 0
// Try to execute 32bit threads.
void VISIBLE32INIT
yield_preempt(void)
// Try to execute 32bit threads.
void VISIBLE32INIT
yield_preempt(void)
PreemptCount++;
switch_next(&MainThread);
}
PreemptCount++;
switch_next(&MainThread);
}
// 16bit code that checks if threads are pending and executes them if so.
void
// 16bit code that checks if threads are pending and executes them if so.
void
|| GET_FLATPTR(MainThread.next) == &MainThread)
return;
|| GET_FLATPTR(MainThread.next) == &MainThread)
return;
- call32(yield_preempt, 0, 0);
+ extern void _cfunc32flat_yield_preempt(void);
+ call32(_cfunc32flat_yield_preempt, 0, 0);
// 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.
// 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.
// 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.
// 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.
# define ASSERT32SEG() __force_link_error__only_in_32bit_segmented()
# define ASSERT32FLAT() __force_link_error__only_in_32bit_flat()
#elif MODESEGMENT == 1
# 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)
# define VISIBLE32INIT VISIBLE32FLAT
# define VISIBLE32SEG __VISIBLE
# define VAR16 __section(".discard.var16." UNIQSEC)
# define ASSERT32SEG() do { } while (0)
# define ASSERT32FLAT() __force_link_error__only_in_32bit_flat()
#else
# 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 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
# define VAR16 __section(".discard.var16." UNIQSEC)
# define VAR16VISIBLE VAR16 __VISIBLE __weak
# define VAR16EXPORT VAR16VISIBLE
for reloc in section.relocs:
symbol = reloc.symbol
if (symbol.section is None
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):
+ 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
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
return out
# Write LD script includes for the given sections using relative offsets
# Section garbage collection
######################################################################
# Section garbage collection
######################################################################
+CFUNCPREFIX = [('_cfunc16_', 0), ('_cfunc32seg_', 1), ('_cfunc32flat_', 2)]
+
# Find and keep the section associated with a symbol (if available).
# 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
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
reloc.symbol = symbol
keepsection(symbol.section, infos, pos)
return 0
section.keep = 1
# Keep all sections that this section points to
for reloc in section.relocs:
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
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)
- ret = keepsymbol(reloc, infos, (pos+2)%3)
+ ret = keepsymbol(reloc, infos, (pos+2)%3, 1)
name = size = alignment = fileid = relocs = None
finalloc = category = keep = None
class Reloc:
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
class Symbol:
name = offset = section = None
reloc = Reloc()
reloc.offset = int(off, 16)
reloc.type = type
reloc = Reloc()
reloc.offset = int(off, 16)
reloc.type = type
+ reloc.symbolname = symbolname
reloc.symbol = symbols[symbolname]
relocsection.relocs.append(reloc)
except ValueError:
reloc.symbol = symbols[symbolname]
relocsection.relocs.append(reloc)
except ValueError:
findInit(sections)
# Determine the final memory locations of each kept section.
findInit(sections)
# Determine the final memory locations of each kept section.
- # locsX = [(addr, sectioninfo), ...]
doLayout(sections)
# Write out linker script files.
doLayout(sections)
# Write out linker script files.