kernel: Integrate lexical regions

046eddc2e8a03dc1e9cdee94c56fcef61d4d76c08e01648219c38792d564ad1d
Alexis Sellier committed ago 1 parent 807886ea
Makefile +90 -3
7 7
TEST_FIXTURE_STD := -pkg std $(patsubst %,-mod %,$(TEST_FIXTURE_STD_LIB))
8 8
9 9
# Full standard library with test modules.
10 10
STD_TEST := $(STD) $(patsubst %,-mod %,$(shell cat std.lib.test))
11 11
12 +
# Standard library support for tests in another package.
13 +
STD_TEST_SUPPORT := $(STD) -mod lib/std/testing.rad
14 +
12 15
# Source files.
13 16
STD_LIB := $(shell find lib -name '*.rad')
14 17
BIN_DIR := bin
15 18
RAD_BIN := $(BIN_DIR)/radiance.rv64.dev
16 19
17 20
# Emulator command used to invoke the self-hosted compiler.
18 21
EMU       := $(or $(RAD_EMULATOR),emulator)
19 22
EMU_FLAGS := -memory-size=385024 \
20 23
			 -data-size=348160 \
21 -
			 -stack-size=512 \
24 +
			 -stack-size=1024 \
22 25
			 -count-instructions
23 26
RADIANCE  := $(EMU) $(EMU_FLAGS) -run $(RAD_BIN)
24 27
25 28
# Verify the emulator binary exists.
26 29
EMU_PATH := $(shell command -v $(EMU) 2>/dev/null)
27 30
28 31
default: emulator $(RAD_BIN)
29 -
test: emulator seed-test std-test bin-test
32 +
test: emulator seed-test std-test bin-test kernel-test package-test machine-test kernel-acceptance kernel-size-check
30 33
31 34
seed-test:
32 35
	@seed/test
33 36
34 37
# Emulator command check
67 70
	@rm -f lib/std.test.rv64 \
68 71
		lib/std.test.rv64.debug \
69 72
		lib/std.test.rv64.s \
70 73
		lib/std.test.rv64.o
71 74
75 +
# Kernel modules and tests use a separate package and test entry point.
76 +
KERNEL_SRC := kernel/kernel.rad $(shell find kernel/kernel -name '*.rad' ! -name 'tests.rad' ! -path '*/tests/*' 2>/dev/null)
77 +
KERNEL_ASM := kernel/kernel/boot.ras kernel/kernel/sync.ras kernel/kernel/trap.ras kernel/kernel/pages.ras kernel/kernel/loader.ras kernel/kernel/instances.ras kernel/kernel/domains.ras kernel/kernel/dispatch.ras kernel/kernel/calls.ras kernel/kernel/plic.ras
78 +
KERNEL_TEST_SRC := kernel/kernel/tests.rad $(shell find kernel/kernel/tests -name '*.rad' 2>/dev/null)
79 +
KERNEL := -pkg kernel $(patsubst %,-mod %,$(sort $(KERNEL_SRC)))
80 +
KERNEL_TEST := $(BIN_DIR)/kernel.test.rv64
81 +
82 +
kernel-test: emulator $(KERNEL_TEST)
83 +
	@$(EMU) $(EMU_FLAGS) -run $(KERNEL_TEST)
84 +
	@sh test/slots/run "$(EMU)" $(STD_TEST_SUPPORT) $(KERNEL) $(patsubst %,-mod %,$(KERNEL_TEST_SRC))
85 +
86 +
$(KERNEL_TEST): $(KERNEL_SRC) $(KERNEL_TEST_SRC) $(KERNEL_ASM) $(STD_LIB) $(RAD_BIN)
87 +
	@echo "radiance kernel tests => $@"
88 +
	@$(RADIANCE) -test $(STD_TEST_SUPPORT) $(KERNEL) $(patsubst %,-mod %,$(KERNEL_TEST_SRC) $(KERNEL_ASM)) -entry kernel -o $@
89 +
90 +
$(BIN_DIR)/kernel.ril $(BIN_DIR)/std.ril &: $(KERNEL_SRC) $(STD_LIB) $(RAD_BIN)
91 +
	@$(RADIANCE) $(STD) $(KERNEL) -entry kernel -ril $(BIN_DIR)
92 +
93 +
$(BIN_DIR)/kernel.build.rv64: kernel/tools/build.rad $(STD_LIB) $(RAD_BIN)
94 +
	@$(RADIANCE) $(STD) -pkg build -mod $< -entry build -o $@
95 +
96 +
# User packages share the ABI source through a staged package module tree.
97 +
$(BIN_DIR)/root.ril $(BIN_DIR)/scheduler.ril &: kernel/root.rad kernel/scheduler.rad kernel/mmio.rad kernel/kernel/abi.rad kernel/kernel/sys.rad $(RAD_BIN)
98 +
	@mkdir -p $(BIN_DIR)/user/root $(BIN_DIR)/user/scheduler
99 +
	@cp kernel/root.rad kernel/scheduler.rad $(BIN_DIR)/user/
100 +
	@cp kernel/kernel/abi.rad kernel/kernel/sys.rad $(BIN_DIR)/user/root/
101 +
	@cp kernel/kernel/abi.rad kernel/kernel/sys.rad kernel/mmio.rad $(BIN_DIR)/user/scheduler/
102 +
	@$(RADIANCE) -pkg root -mod $(BIN_DIR)/user/root.rad -mod $(BIN_DIR)/user/root/abi.rad -mod $(BIN_DIR)/user/root/sys.rad -entry root -ril $(BIN_DIR)
103 +
	@$(RADIANCE) -pkg scheduler -mod $(BIN_DIR)/user/scheduler.rad -mod $(BIN_DIR)/user/scheduler/abi.rad -mod $(BIN_DIR)/user/scheduler/sys.rad -mod $(BIN_DIR)/user/scheduler/mmio.rad -entry scheduler -ril $(BIN_DIR)
104 +
105 +
$(BIN_DIR)/kernel.rv64: $(BIN_DIR)/root.ril $(BIN_DIR)/scheduler.ril $(BIN_DIR)/std.ril $(BIN_DIR)/kernel.ril $(BIN_DIR)/kernel.build.rv64 $(KERNEL_ASM)
106 +
	@cat $(KERNEL_ASM) > $(BIN_DIR)/kernel.ras
107 +
	@$(EMU) $(EMU_FLAGS) -run $(BIN_DIR)/kernel.build.rv64 -- $(BIN_DIR)/std.ril $(BIN_DIR)/kernel.ril $(BIN_DIR)/kernel.ras $@ $(BIN_DIR)/root.ril $(BIN_DIR)/scheduler.ril
108 +
109 +
# Separate binary package emission, linkage, and decode checks.
110 +
package-test: emulator $(BIN_DIR)/packages.check.rv64 $(BIN_DIR)/shared.build.rv64
111 +
	@sh test/packages/run
112 +
	@RAD_EMULATOR="$(EMU)" test/shared/run
113 +
114 +
$(BIN_DIR)/packages.check.rv64: test/packages/check.rad $(STD_LIB) $(RAD_BIN)
115 +
	@$(RADIANCE) $(STD) -pkg check -mod $< -entry check -o $@
116 +
117 +
$(BIN_DIR)/native.build.rv64: test/native/build.rad $(STD_LIB) $(RAD_BIN)
118 +
	@$(RADIANCE) $(STD) -pkg build -mod $< -entry build -o $@
119 +
120 +
$(BIN_DIR)/native.fixture.rv64: $(BIN_DIR)/native.build.rv64
121 +
	@$(EMU) -run $< -- $@
122 +
123 +
$(BIN_DIR)/shared.build.rv64: test/shared/build.rad $(STD_LIB) $(RAD_BIN)
124 +
	@$(RADIANCE) $(STD) -pkg build -mod $< -entry build -o $@
125 +
126 +
# Native architecture and machine-boundary checks.
127 +
machine-test: emulator $(BIN_DIR)/native.fixture.rv64 $(BIN_DIR)/sync.build.rv64
128 +
	@$(EMU) -machine -run $(BIN_DIR)/native.fixture.rv64
129 +
	@RAD_EMULATOR="$(EMU)" test/sync/run
130 +
	@RAD_EMULATOR="$(EMU)" sh test/trap/run
131 +
	@RAD_EMULATOR="$(EMU)" sh test/pages/run
132 +
133 +
$(BIN_DIR)/sync.build.rv64: test/sync/build.rad $(STD_LIB) $(RAD_BIN)
134 +
	@$(RADIANCE) $(STD) -pkg build -mod $< -entry build -o $@
135 +
72 136
# Binary Tests
73 137
74 138
BIN_TEST_DIR := test/tests
75 139
# Only tests with `//! returns:` are compiled to binaries and executed.
76 140
BIN_TEST_EXE_SRC := $(shell grep -rl '^//! returns:' $(BIN_TEST_DIR))
130 194
clean: clean-std-test clean-bin-test clean-rad
131 195
132 196
t: test
133 197
c: clean
134 198
135 -
.PHONY: test clean default seed-test std-test bin-test seed \
199 +
.PHONY: test clean default seed-test std-test bin-test kernel-test package-test machine-test kernel-acceptance \
200 +
	kernel-size-check acceptance seed \
136 201
	clean-std-test clean-bin-test clean-rad emulator
137 202
.SUFFIXES:
138 203
.DELETE_ON_ERROR:
139 204
.SILENT:
205 +
206 +
# Full-kernel scenarios that require native execution or distinct fixture images.
207 +
kernel-acceptance: emulator $(RAD_BIN) $(BIN_DIR)/kernel.build.rv64 $(BIN_DIR)/kernel.rv64
208 +
	@RAD_EMULATOR="$(EMU)" sh test/boot/run
209 +
	@RAD_EMULATOR="$(EMU)" sh test/loader/run
210 +
	@RAD_EMULATOR="$(EMU)" sh test/dispatch/run
211 +
	@RAD_EMULATOR="$(EMU)" sh test/dispatch/run smp "1 2 8" 7
212 +
	@RAD_EMULATOR="$(EMU)" sh test/dispatch/run termination
213 +
	@RAD_EMULATOR="$(EMU)" sh test/runtime/run
214 +
	@RAD_EMULATOR="$(EMU)" sh test/bootstrap/run
215 +
	@RAD_EMULATOR="$(EMU)" sh test/dispatch/run mmio
216 +
	@RAD_EMULATOR="$(EMU)" sh test/cycles/run
217 +
	@RAD_EMULATOR="$(EMU)" sh test/scheduling/run
218 +
219 +
# Physical source-line limits and fixed native image memory.
220 +
.PHONY: kernel-size-check
221 +
kernel-size-check: $(BIN_DIR)/kernel.rv64
222 +
	@python3 test/acceptance/sizes
223 +
224 +
# Full sibling-emulator validation with retained acceptance reports.
225 +
acceptance:
226 +
	@sh test/acceptance/run
kernel/kernel/backing.rad +6 -8
76 76
        set store.used = object.index + 1;
77 77
    }
78 78
    set store.records[object.index].run = run;
79 79
    set store.records[object.index].pages = 1;
80 80
    set store.records[object.index].exposed = 1;
81 -
    let mut bits = bitset::init(&mut store.records[object.index].exposures[..]);
82 -
    bitset::put(&mut bits, origin.index);
81 +
    bitset::clearAll(&mut store.records[object.index].exposures[..]);
82 +
    bitset::put(&mut store.records[object.index].exposures[..], origin.index);
83 83
    return try! slots::commit(&mut store.slots[..], reservation);
84 84
}
85 85
86 86
/// Require a live generation-bearing backing reference.
87 87
fn require(store: &Store, object: abi::Ref) throws (abi::Error) {
106 106
export unsafe fn expose(store: &mut Store, object: abi::Ref, domain: abi::Ref) throws (abi::Error) {
107 107
    try require(store, object);
108 108
    if store.records[object.index].pages == 0 or not domainLive(store, domain) {
109 109
        throw abi::Error::BadHandle;
110 110
    }
111 -
    let mut bits = bitset::new(&mut store.records[object.index].exposures[..]);
112 -
    if bitset::contains(&bits, domain.index) {
111 +
    if bitset::contains(&store.records[object.index].exposures[..], domain.index) {
113 112
        return;
114 113
    }
115 -
    bitset::put(&mut bits, domain.index);
114 +
    bitset::put(&mut store.records[object.index].exposures[..], domain.index);
116 115
    set store.records[object.index].exposed += 1;
117 116
}
118 117
119 118
/// Reclaim only when no page object and no domain exposure remains.
120 119
fn reclaim(store: &mut Store, object: abi::Ref, release: fn(&mut frames::Pool, frames::Run) throws (abi::Error)) {
169 168
    let next = first + count;
170 169
    for i in first..next {
171 170
        if store.slots[i].state <> slots::State::Live {
172 171
            continue;
173 172
        }
174 -
        let mut bits = bitset::new(&mut store.records[i].exposures[..]);
175 -
        if not bitset::contains(&bits, domain.index) {
173 +
        if not bitset::contains(&store.records[i].exposures[..], domain.index) {
176 174
            continue;
177 175
        }
178 -
        bitset::clear(&mut bits, domain.index);
176 +
        bitset::clear(&mut store.records[i].exposures[..], domain.index);
179 177
        set store.records[i].exposed -= 1;
180 178
        reclaim(store, abi::Ref { index: i, generation: store.slots[i].generation }, release);
181 179
    }
182 180
    if next < store.used {
183 181
        set store.ending[domain.index] = next + 1;
kernel/tools/build.rad +4 -2
96 96
    emit::loadImm(&mut e, rv64::A3, ro as i64);
97 97
    emit::loadImm(&mut e, rv64::A4, count as i64);
98 98
    emit::loadImm(&mut e, rv64::T0, kernel as i64);
99 99
    emit::emit(&mut e, encode::jalr(rv64::ZERO, rv64::T0, 0));
100 100
    assert e.codeLen <= 1024;
101 -
    for word, i in emit::getCode(&e) {
102 -
        set NATIVE[i] = word;
101 +
    let codeEmitter: 'code = &e in {
102 +
        for word, i in emit::getCode 'code (codeEmitter) {
103 +
            set NATIVE[i] = word;
104 +
        }
103 105
    }
104 106
}
105 107
106 108
/// Link shared boot packages, retain their catalog, and instantiate the kernel graph.
107 109
@default unsafe fn main(env: *sys::Env) -> i32 {
test/modules/run deleted +0 -21
1 -
#!/bin/sh
2 -
# Resolve and execute references beyond module index 127.
3 -
set -eu
4 -
emulator=${RAD_EMULATOR:-emulator}
5 -
work=$(mktemp -d)
6 -
trap 'rm -rf "$work"' EXIT HUP INT TERM
7 -
mkdir "$work/capacity"
8 -
set -- -pkg capacity -mod "$work/capacity.rad"
9 -
index=0
10 -
while [ "$index" -lt 127 ]; do
11 -
    printf 'export mod m%s;\n' "$index" >> "$work/capacity.rad"
12 -
    printf '/// Return this module index.\nexport fn value() -> u64 { return %s; }\n' "$index" > "$work/capacity/m$index.rad"
13 -
    set -- "$@" -mod "$work/capacity/m$index.rad"
14 -
    index=$((index + 1))
15 -
done
16 -
printf 'use capacity::m126;\n/// Check a package root beyond module index 127.\n@default fn main() -> u64 { assert m126::value() == 126; return 0; }\n' > "$work/entry.rad"
17 -
set -- "$@" -pkg entry -mod "$work/entry.rad"
18 -
"$emulator" -memory-size=385024 -data-size=348160 -stack-size=1024 \
19 -
    -run bin/radiance.rv64.dev "$@" -entry entry -o "$work/capacity.rv64"
20 -
"$emulator" -run "$work/capacity.rv64"
21 -
printf 'module scopes: references beyond index 127 passed\n'
test/native/build.rad +1 -1
74 74
        },
75 75
    ];
76 76
    unsafe static symbols: [data::DataSym; 2] = undefined;
77 77
    let mut ro: [u8; 8] = [0; 8];
78 78
    let mut rw: [u8; 8] = [0; 8];
79 -
    let result = try! rv64::finishProgram(&mut generator, globals,
79 +
    let result = try! rv64::finishProgram(generator, globals,
80 80
        rv64::Storage { dataSyms: &mut symbols[..], dataSymEntries: &mut ENTRIES[..] },
81 81
        &[], &mut ro[..], &mut rw[..]);
82 82
    let header = try! image::header(result.layout);
83 83
    let code = @sliceOf(result.code.ptr as *u8, result.code.len * 4);
84 84
    let fd = unix::openOpts(env.args[1], unix::OpenFlags(*unix::O_WRONLY | *unix::O_CREAT | *unix::O_TRUNC), 420);
test/shared/build.rad +4 -2
133 133
    }
134 134
    for i in 0..TEXT.len {
135 135
        set TEXT[i] = encode::nop();
136 136
    }
137 137
    assert e.codeLen <= 1024;
138 -
    for word, i in emit::getCode(&e) {
139 -
        set TEXT[i] = word;
138 +
    let codeEmitter: 'code = &e in {
139 +
        for word, i in emit::getCode 'code (codeEmitter) {
140 +
            set TEXT[i] = word;
141 +
        }
140 142
    }
141 143
    for package, i in &catalog[..] {
142 144
        assert package.code.len <= 1024;
143 145
        for word, j in package.code {
144 146
            set TEXT[1024 + i * 1024 + j] = word;