
XEN_COMPILE_ARCH ?= $(shell uname -m | sed -e s/i.86/x86_32/ \
		      -e s/i86pc/x86_32/ -e s/amd64/x86_64/)
XEN_TARGET_ARCH  ?= $(XEN_COMPILE_ARCH)

X86_32_only := $(if $(filter x86_32,$(XEN_TARGET_ARCH)),,not-)
X86_64_only := $(if $(filter x86_64,$(XEN_TARGET_ARCH)),,not-)

$(X86_32_only)CROSS_ELF_CC = i386-elf-gcc-4.3.2
$(X86_32_only)CROSS_ELF_LD = i386-elf-ld
$(X86_64_only)CROSS_ELF_CC = x86_64-elf-gcc
$(X86_64_only)CROSS_ELF_LD = x86_64-elf-ld
ELF_CC = $(shell type $(CROSS_ELF_CC) >/dev/null 2>&1 && echo $(CROSS_ELF_CC) \
	|| echo $(CC))
ELF_LD = $(shell type $(CROSS_ELF_LD) >/dev/null 2>&1 && echo $(CROSS_ELF_LD) \
	|| echo $(LD))

CFLAGS += -g
LDFLAGS += -g

CFLAGS += -DNO_EXCEPTION_RECORD_HOOK

BASEDIR ?= $(shell pwd)

DESTDIR =

all: hxen-check

clean:
	rm -f hxen.elf hxen.lds
	rm -f include/asm/asm-offsets.h include/xen/compile.h
	rm -f hxen_prog
	rm -f $(KXEN_OBJS)
	rm -rf .deps include/asm
	rm -f .banner
	$(MAKE) -C tools clean

KXEN_SRCS = head.S hxen_main.c
KXEN_SRCS += common/bitmap.c
KXEN_SRCS += common/domain.c
KXEN_SRCS += common/domctl.c
KXEN_SRCS += common/event_channel.c
KXEN_SRCS += common/grant_table.c
KXEN_SRCS += common/kernel.c
KXEN_SRCS += common/keyhandler.c
KXEN_SRCS += common/memory.c
KXEN_SRCS += common/lib.c
KXEN_SRCS += common/page_alloc.c
KXEN_SRCS += common/perfc.c
KXEN_SRCS += common/rangeset.c
KXEN_SRCS += common/rcupdate.c
KXEN_SRCS += common/schedule.c
KXEN_SRCS += common/sched_host.c
KXEN_SRCS += common/shutdown.c
KXEN_SRCS += common/softirq.c
KXEN_SRCS += common/string.c
KXEN_SRCS += common/symbols.c
KXEN_SRCS += common/trace.c
KXEN_SRCS += common/time.c
KXEN_SRCS += common/timer.c
KXEN_SRCS += common/version.c
KXEN_SRCS += common/vsprintf.c
KXEN_SRCS += common/xmalloc.c
KXEN_SRCS += drivers/char/console.c
KXEN_SRCS += drivers/char/ns16550.c
KXEN_SRCS += drivers/char/serial.c
KXEN_SRCS += arch/x86/bitops.c
KXEN_SRCS += arch/x86/clear_page.S
KXEN_SRCS += arch/x86/delay.c
KXEN_SRCS += arch/x86/domain.c
KXEN_SRCS += arch/x86/domctl.c
KXEN_SRCS += arch/x86/flushtlb.c
KXEN_SRCS += arch/x86/i387.c
KXEN_SRCS += arch/x86/irq.c
KXEN_SRCS += arch/x86/mm.c
KXEN_SRCS += arch/x86/nmi.c
KXEN_SRCS += arch/x86/numa.c
KXEN_SRCS += arch/x86/setup.c
KXEN_SRCS += arch/x86/shutdown.c
KXEN_SRCS += arch/x86/smp.c
KXEN_SRCS += arch/x86/smpboot.c
KXEN_SRCS += arch/x86/string.c
KXEN_SRCS += arch/x86/time.c
KXEN_SRCS += arch/x86/traps.c
KXEN_SRCS += arch/x86/usercopy.c
KXEN_SRCS += arch/x86/x86_emulate.c
KXEN_SRCS += arch/x86/cpu/common.c
KXEN_SRCS += arch/x86/cpu/intel.c
KXEN_SRCS += arch/x86/cpu/intel_cacheinfo.c
KXEN_SRCS += arch/x86/hvm/emulate.c
KXEN_SRCS += arch/x86/hvm/i8254.c
KXEN_SRCS += arch/x86/hvm/intercept.c
KXEN_SRCS += arch/x86/hvm/io.c
KXEN_SRCS += arch/x86/hvm/irq.c
KXEN_SRCS += arch/x86/hvm/hpet.c
KXEN_SRCS += arch/x86/hvm/hvm.c
KXEN_SRCS += arch/x86/hvm/mtrr.c
KXEN_SRCS += arch/x86/hvm/pmtimer.c
KXEN_SRCS += arch/x86/hvm/rtc.c
KXEN_SRCS += arch/x86/hvm/stdvga.c
KXEN_SRCS += arch/x86/hvm/vioapic.c
KXEN_SRCS += arch/x86/hvm/viridian.c
KXEN_SRCS += arch/x86/hvm/vlapic.c
KXEN_SRCS += arch/x86/hvm/vpic.c
KXEN_SRCS += arch/x86/hvm/vpt.c
KXEN_SRCS += arch/x86/hvm/vmx/entry.S
KXEN_SRCS += arch/x86/hvm/vmx/intr.c
KXEN_SRCS += arch/x86/hvm/vmx/realmode.c
KXEN_SRCS += arch/x86/hvm/vmx/vmx.c
KXEN_SRCS += arch/x86/hvm/vmx/vmcs.c
# KXEN_SRCS += arch/x86/mm/guest_walk.c  ==> guest_walk_X.o below
KXEN_SRCS += arch/x86/mm/paging.c
KXEN_SRCS += arch/x86/mm/p2m.c
KXEN_SRCS += arch/x86/mm/hap/hap.c
KXEN_SRCS += arch/x86/mm/shadow/common.c
# KXEN_SRCS += arch/x86/mm/shadow/multi.c  ==> guest_X.o below
KXEN_SRCS += arch/x86/$(XEN_TARGET_ARCH)/traps.c

KXEN_CFLAGS  = $(CFLAGS)
$(X86_32_only)KXEN_CFLAGS += -m32 -march=i686
$(X86_64_only)KXEN_CFLAGS += -m64 -D__KXEN_X64_BROKEN
# $(X86_64_only)KXEN_CFLAGS += -O2
$(X86_64_only)KXEN_CFLAGS += -mcmodel=large
# flags copied from 64 bit xen
# $(X86_64_only)KXEN_CFLAGS += -fomit-frame-pointer
$(X86_64_only)KXEN_CFLAGS += -fno-stack-protector
$(X86_64_only)KXEN_CFLAGS += -mno-red-zone
$(X86_64_only)KXEN_CFLAGS += -fno-reorder-blocks
$(X86_64_only)KXEN_CFLAGS += -fno-asynchronous-unwind-tables
KXEN_CFLAGS += -fno-strict-aliasing -std=gnu99
KXEN_CFLAGS += -Wall -Wstrict-prototypes -Wno-unused-value
KXEN_CFLAGS += -Wdeclaration-after-statement
KXEN_CFLAGS += -nostdinc
KXEN_CFLAGS += -fno-builtin -fno-common
KXEN_CFLAGS += -iwithprefix include
KXEN_CFLAGS += -Werror -Wno-pointer-arith -pipe
KXEN_CFLAGS += -I$(BASEDIR)/include
KXEN_CFLAGS += -I$(BASEDIR)/include/asm/mach-generic
KXEN_CFLAGS += -I$(BASEDIR)/include/asm/mach-default
KXEN_CFLAGS += -msoft-float
#KXEN_CFLAGS += -mms-bitfields
KXEN_CFLAGS += -D__XEN__ -D__KXEN__
KXEN_CFLAGS += -Wp,-MD,.deps/$(subst /,_,$@).d -Wp,-MT,$@
KXEN_CFLAGS += -DPERF_COUNTERS

KXEN_OBJS = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(KXEN_SRCS)))
KXEN_OBJS += arch/x86/mm/shadow/guest_2.o
KXEN_OBJS += arch/x86/mm/shadow/guest_3.o
$(X86_64_only)KXEN_OBJS += arch/x86/mm/shadow/guest_4.o
KXEN_OBJS += arch/x86/mm/guest_walk_2.o
KXEN_OBJS += arch/x86/mm/guest_walk_3.o
$(X86_64_only)KXEN_OBJS += arch/x86/mm/guest_walk_4.o

hxen.lds $(KXEN_OBJS) arch/x86/$(XEN_TARGET_ARCH)/asm-offsets.s: include/asm/.exists .deps/.exists
$(KXEN_OBJS): include/asm/asm-offsets.h include/xen/compile.h

%.o: %.c
	$(ELF_CC) $(KXEN_CFLAGS) -c $< -o $@

arch/x86/bitops.o : %.o: %.c
	$(ELF_CC) $(KXEN_CFLAGS) -Wa,--divide -c $< -o $@

%.o : %.S
	$(ELF_CC) $(KXEN_CFLAGS) -D__ASSEMBLY__ -c $< -o $@

arch/x86/mm/shadow/guest_%.o: arch/x86/mm/shadow/multi.c
	$(ELF_CC) $(KXEN_CFLAGS) -DGUEST_PAGING_LEVELS=$* -c $< -o $@

arch/x86/mm/guest_walk_%.o: arch/x86/mm/guest_walk.c
	$(ELF_CC) $(KXEN_CFLAGS) -DGUEST_PAGING_LEVELS=$* -c $< -o $@

hxen-check: hxen.elf
	@echo
	@printf "undefined references: "
	@$(ELF_LD) -Ttext 0x80000000 -g -o $@ $< 2>&1 | grep undefined.ref | tee /dev/tty | wc -l

hxen.elf: hxen.lds $(KXEN_OBJS)
	$(ELF_LD) $(LDFLAGS) -T hxen.lds -r -N $(KXEN_OBJS) -o $@

hxen.lds: hxen.lds.S include/asm/asm-offsets.h
	$(ELF_CC) -P -E -Ui386 $(KXEN_CFLAGS) -D__ASSEMBLY__ -o $@ $<

$(X86_32_only)KXEN_RELOC_ADDR ?= 0x80000000
$(X86_64_only)KXEN_RELOC_ADDR ?= 0xFFFFFFFF80000000

hxen: hxen-abs.lds $(KXEN_OBJS)
	$(ELF_LD) $(LDFLAGS) -T hxen-abs.lds -r -N $(KXEN_OBJS) -o $@

.PHONY: hxen-abs.lds
hxen-abs.lds: hxen.lds.S include/asm/asm-offsets.h
	$(ELF_CC) -P -E -Ui386 $(KXEN_CFLAGS) -D__ASSEMBLY__ \
	  -DKXEN_RELOC_ADDR=$(KXEN_RELOC_ADDR) -o $@ $<

.deps/.exists:
	mkdir -p $(@D)
	touch $@

include/asm/.exists:
	ln -s asm-x86 include/asm

# This is the correct place to edit the build version.
# All other places this is stored (eg. compile.h) should be autogenerated.
export XEN_VERSION       = 3
export XEN_SUBVERSION    = 3
export XEN_EXTRAVERSION ?= .1-hxen$(XEN_VENDORVERSION)
export XEN_FULLVERSION   = $(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION)
-include xen-version

export XEN_WHOAMI	?= $(USER)
export XEN_DOMAIN	?= $(shell ([ -x /bin/dnsdomainname ] && /bin/dnsdomainname) || ([ -x /bin/domainname ] && /bin/domainname || echo [unknown]))

.banner: Makefile
	$(MAKE) -C tools
	@tools/figlet/figlet -d tools/figlet HXen $(XEN_FULLVERSION) 2>$@2 >$@1
	@cat $@1 $@2 >$@
	@rm -f $@1 $@2

# compile.h contains dynamic build info. Rebuilt on every 'make' invocation.
include/xen/compile.h: include/xen/compile.h.in .banner
	@sed -e 's/@@date@@/$(shell LC_ALL=C date)/g' \
	    -e 's/@@time@@/$(shell LC_ALL=C date +%T)/g' \
	    -e 's/@@whoami@@/$(XEN_WHOAMI)/g' \
	    -e 's/@@domain@@/$(XEN_DOMAIN)/g' \
	    -e 's/@@hostname@@/$(shell hostname)/g' \
	    -e 's!@@compiler@@!$(shell $(ELF_CC) $(CFLAGS) -v 2>&1 | tail -1)!g' \
	    -e 's/@@version@@/$(XEN_VERSION)/g' \
	    -e 's/@@subversion@@/$(XEN_SUBVERSION)/g' \
	    -e 's/@@extraversion@@/$(XEN_EXTRAVERSION)/g' \
	    -e 's!@@changeset@@!$(XEN_CHANGESET)!g' \
	    < include/xen/compile.h.in > $@.new
	@grep \" .banner >> $@.new
	@grep -v \" .banner
	@mv -f $@.new $@

include/asm/asm-offsets.h: arch/x86/$(XEN_TARGET_ARCH)/asm-offsets.s
	@(set -e; \
	  echo "/*"; \
	  echo " * DO NOT MODIFY."; \
	  echo " *"; \
	  echo " * This file was auto-generated from $<"; \
	  echo " *"; \
	  echo " */"; \
	  echo ""; \
	  echo "#ifndef __ASM_OFFSETS_H__"; \
	  echo "#define __ASM_OFFSETS_H__"; \
	  echo ""; \
	  sed -ne "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"; \
	  echo ""; \
	  echo "#endif") <$< >$@

arch/x86/$(XEN_TARGET_ARCH)/asm-offsets.s: arch/x86/$(XEN_TARGET_ARCH)/asm-offsets.c
	$(ELF_CC) $(KXEN_CFLAGS) -S -o $@ $<

-include .deps/*.d

.PHONY: TAGS
TAGS:
	find . -name '*.[ch]' | xargs etags

.PHONY: tags
tags:
	find . -name '*.[ch]' | xargs ctags

DISTDIR = ../dist

.PHONY: install-headers
install-headers: $(DISTDIR)/.include-xen
	@ :

$(DISTDIR)/.include-xen:
	@mkdir -p $(DISTDIR)/include/xen
	cp -fr include/public/. $(DISTDIR)/include/xen/
	$(MAKE) -C ../tools/include/xen-foreign
	@mkdir -p $(DISTDIR)/include/xen/foreign/
	cp -f ../tools/include/xen-foreign/*.h $(DISTDIR)/include/xen/foreign/
	@echo '$(DISTDIR)/.include-xen: \' >.deps/DISTDIR_.include-xen.d
	@find include/public -type f | \
	  sed -e 's/^/  /' -e 's/$$/ \\/' >>.deps/DISTDIR_.include-xen.d
	@echo >>.deps/DISTDIR_.include-xen.d
	@touch $@

hxen_prog: hxen_prog.o libelf/libelf-loader.o
hxen_prog: libelf/libelf-relocate.o libelf/libelf-tools.o

hxen_prog.o: hxen_mod.c hxen.hex
	$(ELF_CC) -DKXEN_STANDALONE $(CFLAGS) -c -o $@ $<

