1LOCAL_DIR := $(GET_LOCAL_DIR)
2
3MODULE := $(LOCAL_DIR)
4
5MODULE_SRCS += $(LOCAL_DIR)/start.S
6
7MODULE_SRCS += $(LOCAL_DIR)/arch.c
8MODULE_SRCS += $(LOCAL_DIR)/asm.S
9MODULE_SRCS += $(LOCAL_DIR)/exceptions.c
10MODULE_SRCS += $(LOCAL_DIR)/feature.c
11MODULE_SRCS += $(LOCAL_DIR)/fpu_asm.S
12MODULE_SRCS += $(LOCAL_DIR)/mmu.cpp
13MODULE_SRCS += $(LOCAL_DIR)/mp.c
14MODULE_SRCS += $(LOCAL_DIR)/sbi.c
15MODULE_SRCS += $(LOCAL_DIR)/spinlock.c
16MODULE_SRCS += $(LOCAL_DIR)/thread.c
17MODULE_SRCS += $(LOCAL_DIR)/time.c
18
19MODULE_DEPS += lib/libcpp
20
21# one file uses slightly complicated designated initializer
22MODULE_CFLAGS += -Wno-override-init
23
24SMP_MAX_CPUS ?= 1
25RISCV_MMU ?= none
26RISCV_FPU ?= false
27SUBARCH ?= 32
28RISCV_MODE ?= machine
29RISCV_EXTENSION_LIST ?=
30ARCH_RISCV_EMBEDDED ?= false
31ARCH_RISCV_TWOSEGMENT ?= false
32
33GLOBAL_DEFINES += SMP_MAX_CPUS=$(SMP_MAX_CPUS)
34GLOBAL_DEFINES += PLATFORM_HAS_DYNAMIC_TIMER=1
35
36ifeq (true,$(call TOBOOL,$(WITH_SMP)))
37GLOBAL_DEFINES += WITH_SMP=1
38endif
39
40ifeq ($(strip $(RISCV_MODE)),machine)
41$(info RISCV: Machine Mode)
42GLOBAL_DEFINES += RISCV_M_MODE=1
43ifneq ($(RISCV_MMU),none)
44$(error RISCV mmu not supported in machine mode)
45endif
46else ifeq ($(strip $(RISCV_MODE)),supervisor)
47$(info RISCV: Supervisor Mode)
48GLOBAL_DEFINES += RISCV_S_MODE=1
49else
50$(error Unknown RISC-V mode: "$(strip $(RISCV_MODE))" (valid values are "machine", "supervisor"))
51endif
52
53ifeq ($(RISCV_MMU),sv48)
54ifeq ($(SUBARCH),32)
55$(error RISCV: sv48 mmu not supported for 32 bit riscv)
56endif
57$(info RISCV: MMU sv48)
58GLOBAL_DEFINES += RISCV_MMU=48
59WITH_KERNEL_VM ?= 1
60
61# 48 bits split between two 47 bit halves
62KERNEL_ASPACE_BASE := 0xffff800000000000
63KERNEL_ASPACE_SIZE := 0x0000800000000000
64USER_ASPACE_BASE   := 0x0000000001000000
65USER_ASPACE_SIZE   := 0x00007ffffe000000
66
67else ifeq ($(RISCV_MMU),sv39)
68ifeq ($(SUBARCH),32)
69$(error RISCV: sv39 mmu not supported for 32 bit riscv)
70endif
71$(info RISCV: MMU sv39)
72GLOBAL_DEFINES += RISCV_MMU=39
73WITH_KERNEL_VM ?= 1
74
75# 39 bits split between two 38 bit halves
76KERNEL_ASPACE_BASE := 0xffffffc000000000
77KERNEL_ASPACE_SIZE := 0x0000004000000000
78USER_ASPACE_BASE   := 0x0000000001000000
79USER_ASPACE_SIZE   := 0x0000003ffe000000
80
81else ifeq ($(RISCV_MMU),sv32)
82$(info RISCV: MMU sv32)
83GLOBAL_DEFINES += RISCV_MMU=32
84WITH_KERNEL_VM ?= 1
85
86# 32 bits split between two 31 bit halves
87KERNEL_ASPACE_BASE := 0x80000000
88KERNEL_ASPACE_SIZE := 0x80000000
89USER_ASPACE_BASE   := 0x01000000
90USER_ASPACE_SIZE   := 0x7e000000
91
92else ifeq ($(RISCV_MMU),none)
93else
94$(error Unknown RISCV_MMU: "$(strip $(RISCV_MMU))" (valid values are "none", "sv32", "sv39", "sv48"))
95endif
96
97ifeq (true,$(call TOBOOL,$(WITH_KERNEL_VM)))
98
99GLOBAL_DEFINES += \
100    ARCH_HAS_MMU=1 \
101    KERNEL_ASPACE_BASE=$(KERNEL_ASPACE_BASE) \
102    KERNEL_ASPACE_SIZE=$(KERNEL_ASPACE_SIZE) \
103    USER_ASPACE_BASE=$(USER_ASPACE_BASE) \
104    USER_ASPACE_SIZE=$(USER_ASPACE_SIZE)
105
106KERNEL_BASE ?= $(KERNEL_ASPACE_BASE)+$(MEMBASE)
107KERNEL_LOAD_OFFSET ?= 0
108
109GLOBAL_DEFINES += KERNEL_BASE=$(KERNEL_BASE)
110GLOBAL_DEFINES += KERNEL_LOAD_OFFSET=$(KERNEL_LOAD_OFFSET)
111
112else # no kernel vm
113
114KERNEL_BASE ?= $(MEMBASE)
115KERNEL_LOAD_OFFSET ?= 0
116
117endif
118
119ROMBASE ?= 0
120
121GLOBAL_DEFINES += ROMBASE=$(ROMBASE)
122GLOBAL_DEFINES += MEMBASE=$(MEMBASE)
123GLOBAL_DEFINES += MEMSIZE=$(MEMSIZE)
124
125# if ARCH_riscv{32|64}_TOOLCHAIN_PREFIX is set use it as an override
126# for toolchain prefix.
127ifdef ARCH_$(ARCH)$(SUBARCH)_TOOLCHAIN_PREFIX
128    TOOLCHAIN_PREFIX := $(ARCH_$(ARCH)$(SUBARCH)_TOOLCHAIN_PREFIX)
129endif
130
131# default toolchain is riscv{32|64}-elf-. assume its in the path.
132ifndef TOOLCHAIN_PREFIX
133    TOOLCHAIN_PREFIX := riscv$(SUBARCH)-elf-
134endif
135
136ifeq (true,$(call TOBOOL,$(RISCV_FPU)))
137    GLOBAL_DEFINES += RISCV_FPU=1
138endif
139
140# based on a list of optional extensions passed in, collapse the extensions into
141# a string appended to the end of the -march line below
142$(info RISCV_EXTENSION_LIST = $(RISCV_EXTENSION_LIST))
143ifneq ($(RISCV_EXTENSION_LIST),)
144    RISCV_MARCH_EXTENSIONS := _$(subst $(SPACE),_,$(RISCV_EXTENSION_LIST))
145else
146    RISCV_MARCH_EXTENSIONS :=
147endif
148#$(info RISCV_MARCH_EXTENSIONS = $(RISCV_MARCH_EXTENSIONS))
149
150# for the moment simply build all sources the same way, with or without float based on
151# the configuration of the platform
152ARCH_COMPILEFLAGS_FLOAT :=
153ARCH_COMPILEFLAGS_NOFLOAT :=
154
155# based on 32 or 64 bitness, select the right toolchain and some
156# compiler codegen flags
157ifeq ($(SUBARCH),32)
158    ifeq (true,$(call TOBOOL,$(RISCV_FPU)))
159        ARCH_COMPILEFLAGS := -march=rv32gc$(RISCV_MARCH_EXTENSIONS) -mabi=ilp32d
160    else
161        ARCH_COMPILEFLAGS := -march=rv32imac$(RISCV_MARCH_EXTENSIONS) -mabi=ilp32
162    endif
163
164    # override machine for ld -r
165    GLOBAL_MODULE_LDFLAGS += -m elf32lriscv
166else ifeq ($(SUBARCH),64)
167    GLOBAL_DEFINES += IS_64BIT=1
168
169    ifeq (true,$(call TOBOOL,$(RISCV_FPU)))
170        # HACK: use rv64imafdc instead of the equivalent rv64gc due to
171        # older toolchains not supporting the mapping of one to the other
172        # when selecting libgcc.
173        ARCH_COMPILEFLAGS := -march=rv64imafdc$(RISCV_MARCH_EXTENSIONS) -mabi=lp64d -mcmodel=medany
174    else
175        ARCH_COMPILEFLAGS := -march=rv64imac$(RISCV_MARCH_EXTENSIONS) -mabi=lp64 -mcmodel=medany
176    endif
177
178    # override machine for ld -r
179    GLOBAL_MODULE_LDFLAGS += -m elf64lriscv
180else
181    $(error SUBARCH not set or set to something unknown)
182endif
183
184# test to see if -misa-spec=2.2 is a valid switch.
185# misa-spec is added to make sure the compiler picks up the zicsr extension by default.
186MISA_SPEC := $(shell $(TOOLCHAIN_PREFIX)gcc $(ARCH_COMPILEFLAGS) -misa-spec=2.2 -E - < /dev/null > /dev/null 2>1 && echo supported)
187$(info MISA_SPEC = $(MISA_SPEC))
188ifeq ($(MISA_SPEC),supported)
189ARCH_COMPILEFLAGS += -misa-spec=2.2
190endif
191
192# embedded switch sets the default compile optimization and passes
193# a flag to the code to switch other things on
194ifeq (true,$(call TOBOOL,$(ARCH_RISCV_EMBEDDED)))
195ARCH_OPTFLAGS ?= -Os
196GLOBAL_DEFINES += ARCH_RISCV_EMBEDDED=1
197WITH_LINKER_GC ?= 1
198else
199ARCH_OPTFLAGS ?= -O2
200WITH_LINKER_GC ?= 0
201endif
202
203LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(GLOBAL_COMPILEFLAGS) $(ARCH_COMPILEFLAGS) $(GLOBAL_CFLAGS) -print-libgcc-file-name)
204$(info LIBGCC = $(LIBGCC))
205
206# potentially generated files that should be cleaned out with clean make rule
207GENERATED += \
208	$(BUILDDIR)/linker-onesegment.ld \
209	$(BUILDDIR)/linker-twosegment.ld
210
211# rules for generating the linker script
212$(BUILDDIR)/linker-%.ld: $(LOCAL_DIR)/linker-%.ld $(wildcard arch/*.ld) linkerscript.phony
213	@echo generating $@
214	@$(MKDIR)
215	$(NOECHO)sed "s/%BITS%/$(SUBARCH)/g;s/%ROMBASE%/$(ROMBASE)/;s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/;s/%KERNEL_BASE%/$(KERNEL_BASE)/;s/%KERNEL_LOAD_OFFSET%/$(KERNEL_LOAD_OFFSET)/" < $< > $@.tmp
216	@$(call TESTANDREPLACEFILE,$@.tmp,$@)
217
218linkerscript.phony:
219.PHONY: linkerscript.phony
220
221# select the appropriate linker script based on if we're a one or two segment system
222ifeq (true,$(call TOBOOL,$(ARCH_RISCV_TWOSEGMENT)))
223GLOBAL_DEFINES += ARCH_RISCV_TWOSEGMENT=1
224LINKER_SCRIPT += $(BUILDDIR)/linker-twosegment.ld
225# set MAXPAGESIZE to 8 to cause the linker script to pack things in much tighter than
226# a paged sytem would.
227# NOTE: 8 seems to be about as far as you can go. experienced some extra stuffed words
228# when using 4.
229ARCH_LDFLAGS += -z max-page-size=8
230else
231GLOBAL_DEFINES += ARCH_RISCV_TWOSEGMENT=0
232LINKER_SCRIPT += $(BUILDDIR)/linker-onesegment.ld
233endif
234
235$(info ARCH_COMPILEFLAGS = $(ARCH_COMPILEFLAGS))
236
237include make/module.mk
238
239# vim: set ts=4 sw=4 expandtab:
240