Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/754
-gerrit
commit 19d475190af5a6bced0a07bd79b6432e232eef18
Author: Stefan Reinauer <reinauer(a)chromium.org>
Date: Thu Nov 17 12:52:30 2011 -0800
labels should start at the beginning of the line
cosmetical fix
Change-Id: I60d0fa90656f85ecb8acc357fe6518baa773505b
Signed-off-by: Stefan Reinauer <reinauer(a)google.com>
---
src/cpu/x86/lapic/secondary.S | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/cpu/x86/lapic/secondary.S b/src/cpu/x86/lapic/secondary.S
index 5c1e760..dc00b08 100644
--- a/src/cpu/x86/lapic/secondary.S
+++ b/src/cpu/x86/lapic/secondary.S
@@ -47,7 +47,7 @@ _secondary_start:
1: hlt
jmp 1b
- gdtaddr:
+gdtaddr:
.word gdt_limit /* the table limit */
.long gdt /* we know the offset */
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/765
-gerrit
commit 4b848d668c4d804cc7512078805f5b6d7adf0052
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Mon Jan 9 22:05:18 2012 -0800
Make MTRR min hole alignment 64MB
This affects the algorithm when determining when to
transform a range into a larger range with a hole.
It is needed when for when I switch on an 8MB TSEG
and cause the memory maps to go crazy.
Also add header defines for the SMRR.
Change-Id: I1a06ccc28ef139cc79f655a8b19fd3533aca0401
Signed-off-by: Duncan Laurie <dlaurie(a)google.com>
---
src/cpu/x86/mtrr/mtrr.c | 9 ++++++---
src/include/cpu/x86/mtrr.h | 3 +++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c
index 5f5e02b..ed7d93b 100644
--- a/src/cpu/x86/mtrr/mtrr.c
+++ b/src/cpu/x86/mtrr/mtrr.c
@@ -265,13 +265,16 @@ static unsigned int range_to_mtrr(unsigned int reg,
return reg;
}
- if (above4gb == 2 && type == MTRR_TYPE_WRBACK && range_sizek % 0x4000) {
+#define MIN_ALIGN 0x10000 /* 64MB */
+
+ if (above4gb == 2 && type == MTRR_TYPE_WRBACK &&
+ range_sizek > MIN_ALIGN && range_sizek % MIN_ALIGN) {
/*
- * If this range is not divisible by 16MB then instead
+ * If this range is not divisible then instead
* make a larger range and carve out an uncached hole.
*/
hole_startk = range_startk + range_sizek;
- hole_sizek = 0x4000 - (range_sizek % 0x4000);
+ hole_sizek = MIN_ALIGN - (range_sizek % MIN_ALIGN);
range_sizek += hole_sizek;
}
diff --git a/src/include/cpu/x86/mtrr.h b/src/include/cpu/x86/mtrr.h
index 62cb8b7..8b5cc28 100644
--- a/src/include/cpu/x86/mtrr.h
+++ b/src/include/cpu/x86/mtrr.h
@@ -17,6 +17,9 @@
#define MTRRdefTypeEn (1 << 11)
#define MTRRdefTypeFixEn (1 << 10)
+#define SMRRphysBase_MSR 0x1f2
+#define SMRRphysMask_MSR 0x1f3
+
#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/766
-gerrit
commit 44a318b924ebd63ca8a6fcb0c452d095df28132a
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Mon Jan 9 22:11:25 2012 -0800
Add Kconfig options to enable TSEG and set a size
Future CPUs will require TSEG use for SMM
Change-Id: I1432569ece4371d6e12c997e90d66c175fa54c5c
Signed-off-by: Duncan Laurie <dlaurie(a)google.com>
---
src/cpu/x86/Kconfig | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/src/cpu/x86/Kconfig b/src/cpu/x86/Kconfig
index fdbd527..2033a0a 100644
--- a/src/cpu/x86/Kconfig
+++ b/src/cpu/x86/Kconfig
@@ -42,3 +42,11 @@ config LOGICAL_CPUS
config CACHE_ROM
bool
default n
+
+config SMM_TSEG
+ bool
+ default n
+
+config SMM_TSEG_SIZE
+ hex
+ default 0
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/761
-gerrit
commit 0230c2e6b6635ae9aeec21406501e3df5325b0d9
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Thu Dec 22 10:59:40 2011 -0800
MTRR: add alternate allocation method for odd memory maps
With >= 4GB memory installed we get a memory map split in the middle
due to remap that has boundaries that are inconveniently aligned for
MTRRs due to the various UMA regions.
0000MB-2780MB 2780MB RAM (writeback)
2780MB-2782MB 2MB TSEG (uncached/SMRR)
2782MB-2784MB 2MB GFX GTT (uncached)
2784MB-2816MB 32MB GFX UMA (uncached)
2816MB-4096MB 1280MB EMPTY (N/A)
4096MB-5368MB 1272MB RAM (writeback)
5368MB-5376MB 8MB ME UMA (uncached)
The default MTRR allocation method of trying to cover everything
with one MTRR and then carve out a single uncached region does
not work for the GPU aperture which needs write-combining type,
and it also has issues trying to cover the uneven boundaries
in the avaiable variable MTRRs.
My goal was to make a minimal set of changes and avoid modifying
behavior on existing systems with an algorithm that is not always
optimal for a typical memory layout. So the flag 'above4gb=2'
will change these allocation behaviors:
1) Detect the number of available variable MTRRs rather than
limiting to hardcoded value. We need every last MTRR.
2) Don't try to cover all RAM with one MTRR, instead let each
RAM region get covered independently.
3) Don't assume uma_memory_base is part of the last region
and increase the size of that region. In this case the UMA
region is carved out from the lower memory region and it is
already declared as part of the ram region.
4) If a memory region can't be covered with MTRRs >= 16MB then
instead make a larger region and trim it with uncached MTRRs.
Change-Id: I5a60a44ab6d3ae2f46ea6ffa9e3677aaad2485eb
Signed-off-by: Duncan Laurie <dlaurie(a)google.com>
---
src/cpu/x86/mtrr/mtrr.c | 52 ++++++++++++++++++++++++++++++++++++++++------
1 files changed, 45 insertions(+), 7 deletions(-)
diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c
index 9015ad4..8dccfef 100644
--- a/src/cpu/x86/mtrr/mtrr.c
+++ b/src/cpu/x86/mtrr/mtrr.c
@@ -179,6 +179,18 @@ static inline unsigned int fls(unsigned int x)
#endif
#define MTRRS (BIOS_MTRRS + OS_MTRRS)
+static int total_mtrrs = MTRRS;
+static int bios_mtrrs = BIOS_MTRRS;
+
+static void detect_var_mtrrs(void)
+{
+ msr_t msr;
+
+ msr = rdmsr(MTRRcap_MSR);
+
+ total_mtrrs = msr.lo & 0xff;
+ bios_mtrrs = total_mtrrs - 2;
+}
static void set_fixed_mtrrs(unsigned int first, unsigned int last, unsigned char type)
{
@@ -235,6 +247,8 @@ static unsigned int range_to_mtrr(unsigned int reg,
unsigned long next_range_startk, unsigned char type,
unsigned int address_bits, unsigned int above4gb)
{
+ unsigned long hole_startk = 0, hole_sizek = 0;
+
if (!range_sizek) {
/* If there's no MTRR hole, this function will bail out
* here when called for the hole.
@@ -243,7 +257,7 @@ static unsigned int range_to_mtrr(unsigned int reg,
return reg;
}
- if (reg >= BIOS_MTRRS) {
+ if (reg >= bios_mtrrs) {
printk(BIOS_ERR, "Warning: Out of MTRRs for base: %4ldMB, range: %ldMB, type %s\n",
range_startk >>10, range_sizek >> 10,
(type==MTRR_TYPE_UNCACHEABLE)?"UC":
@@ -251,6 +265,16 @@ static unsigned int range_to_mtrr(unsigned int reg,
return reg;
}
+ if (above4gb == 2 && type == MTRR_TYPE_WRBACK && range_sizek % 0x4000) {
+ /*
+ * If this range is not divisible by 16MB then instead
+ * make a larger range and carve out an uncached hole.
+ */
+ hole_startk = range_startk + range_sizek;
+ hole_sizek = 0x4000 - (range_sizek % 0x4000);
+ range_sizek += hole_sizek;
+ }
+
while(range_sizek) {
unsigned long max_align, align;
unsigned long sizek;
@@ -274,11 +298,20 @@ static unsigned int range_to_mtrr(unsigned int reg,
set_var_mtrr(reg++, range_startk, sizek, type, address_bits);
range_startk += sizek;
range_sizek -= sizek;
- if (reg >= BIOS_MTRRS) {
+ if (reg >= bios_mtrrs) {
printk(BIOS_ERR, "Running out of variable MTRRs!\n");
break;
}
}
+
+ if (hole_sizek) {
+ printk(BIOS_DEBUG, "Adding hole at %ldMB-%ldMB\n",
+ hole_startk, hole_startk + hole_sizek);
+ reg = range_to_mtrr(reg, hole_startk, hole_sizek,
+ next_range_startk, MTRR_TYPE_UNCACHEABLE,
+ address_bits, above4gb);
+ }
+
return reg;
}
@@ -325,7 +358,7 @@ void set_var_mtrr_resource(void *gp, struct device *dev, struct resource *res)
{
struct var_mtrr_state *state = gp;
unsigned long basek, sizek;
- if (state->reg >= BIOS_MTRRS)
+ if (state->reg >= bios_mtrrs)
return;
basek = resk(res->base);
sizek = resk(res->size);
@@ -341,7 +374,7 @@ void set_var_mtrr_resource(void *gp, struct device *dev, struct resource *res)
/* Write the range mtrrs */
if (state->range_sizek != 0) {
#if CONFIG_VAR_MTRR_HOLE
- if (state->hole_sizek == 0) {
+ if (state->hole_sizek == 0 && state->above4gb != 2) {
/* We need to put that on to hole */
unsigned long endk = basek + sizek;
state->hole_startk = state->range_startk + state->range_sizek;
@@ -424,6 +457,10 @@ void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb)
var_state.address_bits = address_bits;
var_state.above4gb = above4gb;
+ /* Detect number of variable MTRRs */
+ if (above4gb == 2)
+ detect_var_mtrrs();
+
search_global_resources(
IORESOURCE_MEM | IORESOURCE_CACHEABLE, IORESOURCE_MEM | IORESOURCE_CACHEABLE,
set_var_mtrr_resource, &var_state);
@@ -435,7 +472,8 @@ void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb)
} else {
#if CONFIG_VAR_MTRR_HOLE
// Increase the base range and set up UMA as an UC hole instead
- var_state.range_sizek += (uma_memory_size >> 10);
+ if (above4gb != 2)
+ var_state.range_sizek += (uma_memory_size >> 10);
var_state.hole_startk = (uma_memory_base >> 10);
var_state.hole_sizek = (uma_memory_size >> 10);
@@ -454,7 +492,7 @@ void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb)
printk(BIOS_DEBUG, "DONE variable MTRRs\n");
printk(BIOS_DEBUG, "Clear out the extra MTRR's\n");
/* Clear out the extra MTRR's */
- while(var_state.reg < MTRRS) {
+ while(var_state.reg < total_mtrrs) {
set_var_mtrr(var_state.reg++, 0, 0, 0, var_state.address_bits);
}
@@ -463,7 +501,7 @@ void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb)
* complete ROM now that we actually have RAM.
*/
if (boot_cpu() && (acpi_slp_type != 3)) {
- set_var_mtrr(7, (4096-4)*1024, 4*1024,
+ set_var_mtrr(total_mtrrs-1, (4096-4)*1024, 4*1024,
MTRR_TYPE_WRPROT, address_bits);
}
#endif
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/762
-gerrit
commit c1969e45cad06752cf8288a4320043a8b8bfe6a7
Author: Gabe Black <gabeblack(a)google.com>
Date: Sat Jan 7 01:03:42 2012 -0800
Revamp cbmem.py to use the coreboot tables.
This change makes significant changes to cbmem.py to make it use the
coreboot tables to find the memory console and timestamp areas instead
of looking for the in memory table TOC structure. That appears to be
more robust and gets cbmem.py working again after some unrelated
changes that affected memory layout.
It also introduces some small infrastructure to make accessing C style
structures in physical memory easier and more transparent.
Change-Id: I51833055a50c2d76423520ba6e059bf8fc50adea
Signed-off-by: Gabe Black <gabeblack(a)google.com>
---
util/cbmem/cbmem.py | 267 ++++++++++++++++++++++++++++++---------------------
1 files changed, 158 insertions(+), 109 deletions(-)
diff --git a/util/cbmem/cbmem.py b/util/cbmem/cbmem.py
index 3e8476d..f4f3e88 100755
--- a/util/cbmem/cbmem.py
+++ b/util/cbmem/cbmem.py
@@ -33,29 +33,46 @@ console sections.
'''
import mmap
-import re
import struct
import sys
-import time
-# These definitions follow src/include/cbmem.h
-CBMEM_MAGIC = 0x434f5245
-CBMEM_MAX_ENTRIES = 16
+def get_phys_mem(addr, size):
+ '''Read size bytes from address addr by mmaping /dev/mem'''
-CBMEM_ENTRY_FORMAT = '@LLQQ'
-CONSOLE_HEADER_FORMAT = '@LL'
-TIMESTAMP_HEADER_FORMAT = '@QLL'
-TIMESTAMP_ENTRY_FORMAT = '@LQ'
-
-mf_fileno = 0 # File number of the file providing access to memory.
-
-def align_up(base, alignment):
- '''Increment to the alignment boundary.
-
- Return the next integer larger than 'base' and divisible by 'alignment'.
- '''
-
- return base + alignment - base % alignment
+ mf = open("/dev/mem")
+ delta = addr % 4096
+ mm = mmap.mmap(mf.fileno(), size + delta,
+ mmap.MAP_PRIVATE, offset=(addr - delta))
+ buf = mm.read(size + delta)
+ mf.close()
+ return buf[delta:]
+
+# This class and metaclass make it easier to define and access structures
+# which live in physical memory. To use them, inherit from CStruct and define
+# a class member called struct_members which is a tuple of pairs. The first
+# item in the pair is the type format specifier that should be used with
+# struct.unpack to read that member from memory. The second item is the name
+# that member should have in the resulting object.
+
+class MetaCStruct(type):
+ def __init__(cls, name, bases, dct):
+ struct_members = dct["struct_members"]
+ cls.struct_fmt = "@"
+ for char, name in struct_members:
+ cls.struct_fmt += char
+ cls.struct_len = struct.calcsize(cls.struct_fmt)
+ super(MetaCStruct, cls).__init__(name, bases, dct)
+
+class CStruct(object):
+ __metaclass__ = MetaCStruct
+ struct_members = ()
+
+ def __init__(self, addr):
+ self.raw_memory = get_phys_mem(addr, self.struct_len)
+ values = struct.unpack(self.struct_fmt, self.raw_memory)
+ names = (name for char, name in self.struct_members)
+ for name, value in zip(names, values):
+ setattr(self, name, value)
def normalize_timer(value, freq):
'''Convert timer reading into microseconds.
@@ -96,109 +113,141 @@ def get_cpu_freq():
# Convert reading into Hertz
return float(freq_str) * 1000.0
-def get_mem_size():
- '''Retrieve amount of memory available to the CPU from /proc/meminfo.'''
- mult = {
- 'kB': 1024
- }
- meminfo = open('/proc/meminfo').read()
- m = re.search('MemTotal:.*\n', meminfo)
- mem_string = re.search('MemTotal:.*\n', meminfo).group(0)
- (_, size, mult_name) = mem_string.split()
- return int(size) * mult[mult_name]
-
-def parse_mem_at(addr, format):
- '''Read and parse a memory location.
-
- This function reads memory at the passed in address, parses it according
- to the passed in format specification and returns a list of values.
-
- The first value in the list is the size of data matching the format
- expression, and the rest of the elements of the list are the actual values
- retrieved using the format.
- '''
-
- size = struct.calcsize(format)
- delta = addr % 4096 # mmap requires the offset to be page size aligned.
- mm = mmap.mmap(mf_fileno, size + delta,
- mmap.MAP_PRIVATE, offset=(addr - delta))
- buf = mm.read(size + delta)
- mm.close()
- rv = [size,] + list(struct.unpack(format, buf[delta:size + delta + 1]))
- return rv
-
-def dprint(text):
- '''Debug print function.
-
- Edit it to get the debug output.
- '''
-
- if False:
- print text
-
def process_timers(base):
'''Scan the array of timestamps found in CBMEM at address base.
For each timestamp print the timer ID and the value in microseconds.
'''
- (step, base_time, max_entr, entr) = parse_mem_at(
- base, TIMESTAMP_HEADER_FORMAT)
-
- print('\ntime base %d, total entries %d' % (base_time, entr))
+ class TimestampHeader(CStruct):
+ struct_members = (
+ ("Q", "base_time"),
+ ("L", "max_entr"),
+ ("L", "entr")
+ )
+
+ class TimestampEntry(CStruct):
+ struct_members = (
+ ("L", "timer_id"),
+ ("Q", "timer_value")
+ )
+
+ header = TimestampHeader(base)
+ print('\ntime base %d, total entries %d' % (header.base_time, header.entr))
clock_freq = get_cpu_freq()
- base = base + step
- for i in range(entr):
- (step, timer_id, timer_value) = parse_mem_at(
- base, TIMESTAMP_ENTRY_FORMAT)
- print '%d:%s ' % (timer_id, normalize_timer(timer_value, clock_freq)),
- base = base + step
+ base = base + header.struct_len
+ for i in range(header.entr):
+ timestamp = TimestampEntry(base)
+ print '%d:%s ' % (timestamp.timer_id,
+ normalize_timer(timestamp.timer_value, clock_freq)),
+ base = base + timestamp.struct_len
print
def process_console(base):
'''Dump the console log buffer contents found at address base.'''
- (step, size, cursor) = parse_mem_at(base, CONSOLE_HEADER_FORMAT)
- print 'cursor at %d\n' % cursor
+ class ConsoleHeader(CStruct):
+ struct_members = (
+ ("L", "size"),
+ ("L", "cursor")
+ )
- cons_string_format = '%ds' % min(cursor, size)
- (_, cons_text) = parse_mem_at(base + step, cons_string_format)
+ header = ConsoleHeader(base)
+ print 'cursor at %d\n' % header.cursor
+
+ cons_addr = base + header.struct_len
+ cons_length = min(header.cursor, header.size)
+ cons_text = get_phys_mem(cons_addr, cons_length)
print cons_text
print '\n'
-mem_alignment = 1024 * 1024 * 1024 # 1 GBytes
-table_alignment = 128 * 1024
-
-mem_size = get_mem_size()
-
-# start at memory address aligned at 128K.
-offset = align_up(mem_size, table_alignment)
-
-dprint('mem_size %x offset %x' %(mem_size, offset))
-mf = open("/dev/mem")
-mf_fileno = mf.fileno()
-
-while offset % mem_alignment: # do not cross the 1G boundary while searching
- (step, magic, mid, base, size) = parse_mem_at(offset, CBMEM_ENTRY_FORMAT)
- if magic == CBMEM_MAGIC:
- offset = offset + step
- break
- offset += table_alignment
-else:
- print 'Did not find the CBMEM'
- sys.exit(0)
-
-for i in (range(1, CBMEM_MAX_ENTRIES)):
- (_, magic, mid, base, size) = parse_mem_at(offset, CBMEM_ENTRY_FORMAT)
- if mid == 0:
- break
-
- print '%x, %x, %x' % (mid, base, size)
- if mid == 0x54494d45:
- process_timers(base)
- if mid == 0x434f4e53:
- process_console(base)
-
- offset = offset + step
-
-mf.close()
+def ipchksum(buf):
+ '''Checksumming function used on the coreboot tables. The buffer being
+ checksummed is summed up as if it was an array of 16 bit unsigned
+ integers. If there are an odd number of bytes, the last element is zero
+ extended.'''
+
+ size = len(buf)
+ odd = size % 2
+ fmt = "<%dH" % ((size - odd) / 2)
+ if odd:
+ fmt += "B"
+ shorts = struct.unpack(fmt, buf)
+ checksum = sum(shorts)
+ checksum = (checksum >> 16) + (checksum & 0xffff)
+ checksum += (checksum >> 16)
+ checksum = ~checksum & 0xffff
+ return checksum
+
+def parse_tables(base, length):
+ '''Find the coreboot tables in memory and process whatever we can.'''
+
+ class CBTableHeader(CStruct):
+ struct_members = (
+ ("4s", "signature"),
+ ("I", "header_bytes"),
+ ("I", "header_checksum"),
+ ("I", "table_bytes"),
+ ("I", "table_checksum"),
+ ("I", "table_entries")
+ )
+
+ class CBTableEntry(CStruct):
+ struct_members = (
+ ("I", "tag"),
+ ("I", "size")
+ )
+
+ class CBTableForward(CBTableEntry):
+ struct_members = CBTableEntry.struct_members + (
+ ("Q", "forward"),
+ )
+
+ class CBMemTab(CBTableEntry):
+ struct_members = CBTableEntry.struct_members + (
+ ("L", "cbmem_tab"),
+ )
+
+ for addr in range(base, base + length, 16):
+ header = CBTableHeader(addr)
+ if header.signature == "LBIO":
+ break
+ else:
+ return -1
+
+ if header.header_bytes == 0:
+ return -1
+
+ if ipchksum(header.raw_memory) != 0:
+ print "Bad header checksum"
+ return -1
+
+ addr += header.header_bytes
+ table = get_phys_mem(addr, header.table_bytes)
+ if ipchksum(table) != header.table_checksum:
+ print "Bad table checksum"
+ return -1
+
+ for i in range(header.table_entries):
+ entry = CBTableEntry(addr)
+ if entry.tag == 0x11: # Forwarding entry
+ return parse_tables(CBTableForward(addr).forward, length)
+ elif entry.tag == 0x16: # Timestamps
+ process_timers(CBMemTab(addr).cbmem_tab)
+ elif entry.tag == 0x17: # CBMEM console
+ process_console(CBMemTab(addr).cbmem_tab)
+
+ addr += entry.size
+
+ return 0
+
+def main():
+ for base, length in (0x00000000, 0x1000), (0x000f0000, 0x1000):
+ if parse_tables(base, length):
+ break
+ else:
+ print "Didn't find the coreboot tables"
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main())
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/737
-gerrit
commit 5759acef0583e960ded791b6c962365f5813ac63
Author: Stefan Reinauer <reinauer(a)chromium.org>
Date: Wed Oct 26 22:11:52 2011 +0000
add native memset() function on x86.
Change-Id: Ia118ebe0a4b59bdcefd78895141a365170f6aed2
Signed-off-by: Stefan Reinauer <reinauer(a)google.com>
---
src/arch/x86/Kconfig | 4 ++
src/arch/x86/lib/Makefile.inc | 2 +
src/arch/x86/lib/memset.c | 86 +++++++++++++++++++++++++++++++++++++++++
src/lib/Makefile.inc | 4 ++
4 files changed, 96 insertions(+), 0 deletions(-)
diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig
index 74933af..078ae95 100644
--- a/src/arch/x86/Kconfig
+++ b/src/arch/x86/Kconfig
@@ -80,6 +80,10 @@ config CMOS_DEFAULT_FILE
config BOOTBLOCK_SOUTHBRIDGE_INIT
string
+config HAVE_ARCH_MEMSET
+ bool
+ default y
+
config HAVE_ARCH_MEMCPY
bool
default y
diff --git a/src/arch/x86/lib/Makefile.inc b/src/arch/x86/lib/Makefile.inc
index f99e429..3f4dc95 100644
--- a/src/arch/x86/lib/Makefile.inc
+++ b/src/arch/x86/lib/Makefile.inc
@@ -8,10 +8,12 @@ ramstage-$(CONFIG_MMCONF_SUPPORT) += pci_ops_mmconf.c
ramstage-y += pci_ops_auto.c
ramstage-y += exception.c
ramstage-$(CONFIG_IOAPIC) += ioapic.c
+ramstage-y += memset.c
ramstage-y += memcpy.c
romstage-y += romstage_console.c
romstage-y += cbfs_and_run.c
+romstage-y += memset.c
romstage-y += memcpy.c
smm-y += memcpy.c
diff --git a/src/arch/x86/lib/memset.c b/src/arch/x86/lib/memset.c
new file mode 100644
index 0000000..e850726
--- /dev/null
+++ b/src/arch/x86/lib/memset.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 1991,1992,1993,1997,1998,2003, 2005 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* From glibc-2.14, sysdeps/i386/memset.c */
+
+#include <string.h>
+#include <stdint.h>
+
+typedef uint32_t op_t;
+
+void *memset(void *dstpp, int c, size_t len)
+{
+ int d0;
+ unsigned long int dstp = (unsigned long int) dstpp;
+
+ /* This explicit register allocation improves code very much indeed. */
+ register op_t x asm("ax");
+
+ x = (unsigned char) c;
+
+ /* Clear the direction flag, so filling will move forward. */
+ asm volatile("cld");
+
+ /* This threshold value is optimal. */
+ if (len >= 12) {
+ /* Fill X with four copies of the char we want to fill with. */
+ x |= (x << 8);
+ x |= (x << 16);
+
+ /* Adjust LEN for the bytes handled in the first loop. */
+ len -= (-dstp) % sizeof(op_t);
+
+ /*
+ * There are at least some bytes to set. No need to test for
+ * LEN == 0 in this alignment loop.
+ */
+
+ /* Fill bytes until DSTP is aligned on a longword boundary. */
+ asm volatile(
+ "rep\n"
+ "stosb" /* %0, %2, %3 */ :
+ "=D" (dstp), "=c" (d0) :
+ "0" (dstp), "1" ((-dstp) % sizeof(op_t)), "a" (x) :
+ "memory");
+
+ /* Fill longwords. */
+ asm volatile(
+ "rep\n"
+ "stosl" /* %0, %2, %3 */ :
+ "=D" (dstp), "=c" (d0) :
+ "0" (dstp), "1" (len / sizeof(op_t)), "a" (x) :
+ "memory");
+ len %= sizeof(op_t);
+ }
+
+ /* Write the last few bytes. */
+ asm volatile(
+ "rep\n"
+ "stosb" /* %0, %2, %3 */ :
+ "=D" (dstp), "=c" (d0) :
+ "0" (dstp), "1" (len), "a" (x) :
+ "memory");
+
+ return dstpp;
+}
diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc
index 61b6451..8ce72b2 100644
--- a/src/lib/Makefile.inc
+++ b/src/lib/Makefile.inc
@@ -1,6 +1,8 @@
+ifneq ($(CONFIG_HAVE_ARCH_MEMSET),y)
romstage-y += memset.c
+endif
romstage-y += memchr.c
ifneq ($(CONFIG_HAVE_ARCH_MEMCPY),y)
romstage-y += memcpy.c
@@ -19,7 +21,9 @@ romstage-$(CONFIG_CONSOLE_NE2K) += compute_ip_checksum.c
romstage-$(CONFIG_USBDEBUG) += usbdebug.c
romstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
+ifneq ($(CONFIG_HAVE_ARCH_MEMSET),y)
ramstage-y += memset.c
+endif
ramstage-y += memchr.c
ifneq ($(CONFIG_HAVE_ARCH_MEMCPY),y)
ramstage-y += memcpy.c