Skip to content

Commit cf4b1ad

Browse files
committed
xv6: formatting, cleanup, rev5 (take 2)
1 parent 9c4fe7b commit cf4b1ad

17 files changed

+193
-197
lines changed

Makefile

+11-9
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ initcode: initcode.S
107107
$(OBJCOPY) -S -O binary initcode.out initcode
108108
$(OBJDUMP) -S initcode.o > initcode.asm
109109

110-
kernel: $(OBJS) multiboot.o bootother initcode
111-
$(LD) $(LDFLAGS) -Ttext 0x100000 -e main -o kernel multiboot.o $(OBJS) -b binary initcode bootother fs.img
110+
kernel: $(OBJS) multiboot.o data.o bootother initcode
111+
$(LD) $(LDFLAGS) -Ttext 0x100000 -e main -o kernel multiboot.o data.o $(OBJS) -b binary initcode bootother
112112
$(OBJDUMP) -S kernel > kernel.asm
113113
$(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym
114114

@@ -119,8 +119,8 @@ kernel: $(OBJS) multiboot.o bootother initcode
119119
# great for testing the kernel on real hardware without
120120
# needing a scratch disk.
121121
MEMFSOBJS = $(filter-out ide.o,$(OBJS)) memide.o
122-
kernelmemfs: $(MEMFSOBJS) multiboot.o bootother initcode fs.img
123-
$(LD) $(LDFLAGS) -Ttext 0x100000 -e main -o kernelmemfs multiboot.o $(MEMFSOBJS) -b binary initcode bootother fs.img
122+
kernelmemfs: $(MEMFSOBJS) multiboot.o data.o bootother initcode fs.img
123+
$(LD) $(LDFLAGS) -Ttext 0x100000 -e main -o kernelmemfs multiboot.o data.o $(MEMFSOBJS) -b binary initcode bootother fs.img
124124
$(OBJDUMP) -S kernelmemfs > kernelmemfs.asm
125125
$(OBJDUMP) -t kernelmemfs | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernelmemfs.sym
126126

@@ -251,14 +251,16 @@ dist-test:
251251
rm -rf dist-test
252252
mkdir dist-test
253253
cp dist/* dist-test
254-
cd dist-test; ../m print
255-
cd dist-test; ../m bochs || true
256-
cd dist-test; ../m qemu
254+
cd dist-test; $(MAKE) print
255+
cd dist-test; $(MAKE) bochs || true
256+
cd dist-test; $(MAKE) qemu
257257

258-
# update this rule (change rev1) when it is time to
258+
# update this rule (change rev#) when it is time to
259259
# make a new revision.
260260
tar:
261261
rm -rf /tmp/xv6
262262
mkdir -p /tmp/xv6
263263
cp dist/* dist/.gdbinit.tmpl /tmp/xv6
264-
(cd /tmp; tar cf - xv6) | gzip >xv6-rev4.tar.gz
264+
(cd /tmp; tar cf - xv6) | gzip >xv6-rev5.tar.gz
265+
266+
.PHONY: dist-test dist

bootasm.S

+12-21
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,16 @@
1313
.code16 # Assemble for 16-bit mode
1414
.globl start
1515
start:
16-
cli # BIOS enabled interrupts ; disable
16+
cli # BIOS enabled interrupts; disable
1717

1818
# Set up the important data segment registers (DS, ES, SS).
1919
xorw %ax,%ax # Segment number zero
2020
movw %ax,%ds # -> Data Segment
2121
movw %ax,%es # -> Extra Segment
2222
movw %ax,%ss # -> Stack Segment
2323

24-
# Enable A20:
25-
# For backwards compatibility with the earliest PCs, physical
26-
# address line 20 is tied low, so that addresses higher than
27-
# 1MB wrap around to zero by default. This code undoes this.
24+
# Physical address line A20 is tied to zero so that the first PCs
25+
# with 2 MB would run software that assumed 1 MB. Undo that.
2826
seta20.1:
2927
inb $0x64,%al # Wait for not busy
3028
testb $0x2,%al
@@ -41,28 +39,21 @@ seta20.2:
4139
movb $0xdf,%al # 0xdf -> port 0x60
4240
outb %al,$0x60
4341

44-
//PAGEBREAK!
45-
# Switch from real to protected mode, using a bootstrap GDT
46-
# and segment translation that makes virtual addresses
47-
# identical to physical addresses, so that the
48-
# effective memory map does not change after subsequent
49-
# loads of segment registers.
42+
# Switch from real to protected mode. Use a bootstrap GDT that makes
43+
# virtual addresses map dierctly to physical addresses so that the
44+
# effective memory map doesn't change during the transition.
5045
lgdt gdtdesc
5146
movl %cr0, %eax
5247
orl $CR0_PE, %eax
5348
movl %eax, %cr0
54-
55-
# This ljmp is how you load the CS (Code Segment) register.
56-
# SEG_ASM produces segment descriptors with the 32-bit mode
57-
# flag set (the D flag), so addresses and word operands will
58-
# default to 32 bits after this jump.
59-
ljmp $(SEG_KCODE<<3), $start32
6049

61-
# tell the assembler to generate 0x66 prefixes for 16-bit
62-
# instructions like movw, and to generate 32-bit immediate
63-
# addresses.
64-
.code32
50+
//PAGEBREAK!
51+
# Complete transition to 32-bit protected mode by using long jmp
52+
# to reload %cs and %eip. The segment registers are set up with no
53+
# translation, so that the mapping is still the identity mapping.
54+
ljmp $(SEG_KCODE<<3), $start32
6555

56+
.code32 # Tell assembler to generate 32-bit code now.
6657
start32:
6758
# Set up the protected-mode data segment registers
6859
movw $(SEG_KDATA<<3), %ax # Our data segment selector

bootother.S

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ start:
3434
movw %ax,%es
3535
movw %ax,%ss
3636

37-
//PAGEBREAK!
3837
lgdt gdtdesc
3938
movl %cr0, %eax
4039
orl $CR0_PE, %eax
4140
movl %eax, %cr0
4241

42+
//PAGEBREAK!
4343
ljmp $(SEG_KCODE<<3), $start32
4444

4545
.code32

data.S

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
1-
# Define "data" symbol to mark beginning of data segment.
2-
# Must be linked before any other data on ld command line.
1+
// The kernel layout is:
2+
//
3+
// text
4+
// rodata
5+
// data
6+
// bss
7+
//
8+
// Conventionally, Unix linkers provide pseudo-symbols
9+
// etext, edata, and end, at the end of the text, data, and bss.
10+
// For the kernel mapping, we need the address at the beginning
11+
// of the data section, but that's not one of the conventional
12+
// symbols, because the convention started before there was a
13+
// read-only rodata section between text and data.
14+
//
15+
// To get the address of the data section, we define a symbol
16+
// named data and make sure this is the first object passed to
17+
// the linker, so that it will be the first symbol in the data section.
18+
//
19+
// Alternative approaches would be to parse our own ELF header
20+
// or to write a linker script, but this is simplest.
21+
322
.data
423
.globl data
524
data:

exec.c

+18-44
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ int
1010
exec(char *path, char **argv)
1111
{
1212
char *s, *last;
13-
int i, off, argc;
14-
uint sz, sp, strings[MAXARG];
13+
int i, off;
14+
uint argc, sz, sp, ustack[3+MAXARG+1];
1515
struct elfhdr elf;
1616
struct inode *ip;
1717
struct proghdr ph;
@@ -53,49 +53,25 @@ exec(char *path, char **argv)
5353
if((sz = allocuvm(pgdir, sz, sz + PGSIZE)) == 0)
5454
goto bad;
5555

56-
// initialize stack content:
57-
58-
// "argumentN" -- nul-terminated string
59-
// ...
60-
// "argument0"
61-
// 0 -- argv[argc]
62-
// address of argumentN
63-
// ...
64-
// address of argument0 -- argv[0]
65-
// address of address of argument0 -- argv argument to main()
66-
// argc -- argc argument to main()
67-
// ffffffff -- return PC for main() call
68-
56+
// Push argument strings, prepare rest of stack in ustack.
6957
sp = sz;
70-
71-
// count arguments
72-
for(argc = 0; argv[argc]; argc++)
73-
;
74-
if(argc >= MAXARG)
75-
goto bad;
76-
77-
// push strings and remember where they are
78-
for(i = argc - 1; i >= 0; --i){
79-
sp -= strlen(argv[i]) + 1;
80-
strings[i] = sp;
81-
copyout(pgdir, sp, argv[i], strlen(argv[i]) + 1);
58+
for(argc = 0; argv[argc]; argc++) {
59+
if(argc >= MAXARG)
60+
goto bad;
61+
sp -= strlen(argv[argc]) + 1;
62+
sp &= ~3;
63+
if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
64+
goto bad;
65+
ustack[3+argc] = sp;
8266
}
67+
ustack[3+argc] = 0;
8368

84-
#define PUSH(x){ int xx = (int)(x); sp -= 4; copyout(pgdir, sp, &xx, 4); }
69+
ustack[0] = 0xffffffff; // fake return PC
70+
ustack[1] = argc;
71+
ustack[2] = sp - (argc+1)*4; // argv pointer
8572

86-
PUSH(0); // argv[argc] is zero
87-
88-
// push argv[] elements
89-
for(i = argc - 1; i >= 0; --i)
90-
PUSH(strings[i]);
91-
92-
PUSH(sp); // argv
93-
94-
PUSH(argc);
95-
96-
PUSH(0xffffffff); // in case main tries to return
97-
98-
if(sp < sz - PGSIZE)
73+
sp -= (3+argc+1) * 4;
74+
if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0)
9975
goto bad;
10076

10177
// Save program name for debugging.
@@ -110,9 +86,7 @@ exec(char *path, char **argv)
11086
proc->sz = sz;
11187
proc->tf->eip = elf.entry; // main
11288
proc->tf->esp = sp;
113-
114-
switchuvm(proc);
115-
89+
switchuvm(proc);
11690
freevm(oldpgdir);
11791

11892
return 0;

fs.h

-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ struct dinode {
4141
// Block containing bit for block b
4242
#define BBLOCK(b, ninodes) (b/BPB + (ninodes)/IPB + 3)
4343

44-
// PAGEBREAK: 10
4544
// Directory is a file containing a sequence of dirent structures.
4645
#define DIRSIZ 14
4746

ide.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ ideintr(void)
9696
acquire(&idelock);
9797
if((b = idequeue) == 0){
9898
release(&idelock);
99-
cprintf("Spurious IDE interrupt.\n");
99+
// cprintf("spurious IDE interrupt\n");
100100
return;
101101
}
102102
idequeue = b->qnext;

main.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ bootothers(void)
8989
char *stack;
9090

9191
// Write bootstrap code to unused memory at 0x7000.
92-
// The linker has placed the image of bootother.S in _binary_bootother_start.
92+
// The linker has placed the image of bootother.S in
93+
// _binary_bootother_start.
9394
code = (uchar*)0x7000;
9495
memmove(code, _binary_bootother_start, (uint)_binary_bootother_size);
9596

@@ -111,3 +112,7 @@ bootothers(void)
111112
;
112113
}
113114
}
115+
116+
//PAGEBREAK!
117+
// Blank page.
118+

mp.c

-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ mpsearch1(uchar *addr, int len)
3939
{
4040
uchar *e, *p;
4141

42-
cprintf("mpsearch1 0x%x %d\n", addr, len);
4342
e = addr+len;
4443
for(p = addr; p < e; p += sizeof(struct mp))
4544
if(memcmp(p, "_MP_", 4) == 0 && sum(p, sizeof(struct mp)) == 0)
@@ -113,7 +112,6 @@ mpinit(void)
113112
switch(*p){
114113
case MPPROC:
115114
proc = (struct mpproc*)p;
116-
cprintf("mpproc %d\n", proc->apicid);
117115
if(ncpu != proc->apicid){
118116
cprintf("mpinit: ncpu=%d apicid=%d\n", ncpu, proc->apicid);
119117
ismp = 0;

proc.c

+38-38
Original file line numberDiff line numberDiff line change
@@ -25,44 +25,6 @@ pinit(void)
2525
initlock(&ptable.lock, "ptable");
2626
}
2727

28-
//PAGEBREAK: 36
29-
// Print a process listing to console. For debugging.
30-
// Runs when user types ^P on console.
31-
// No lock to avoid wedging a stuck machine further.
32-
void
33-
procdump(void)
34-
{
35-
static char *states[] = {
36-
[UNUSED] "unused",
37-
[EMBRYO] "embryo",
38-
[SLEEPING] "sleep ",
39-
[RUNNABLE] "runble",
40-
[RUNNING] "run ",
41-
[ZOMBIE] "zombie"
42-
};
43-
int i;
44-
struct proc *p;
45-
char *state;
46-
uint pc[10];
47-
48-
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
49-
if(p->state == UNUSED)
50-
continue;
51-
if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
52-
state = states[p->state];
53-
else
54-
state = "???";
55-
cprintf("%d %s %s", p->pid, state, p->name);
56-
if(p->state == SLEEPING){
57-
getcallerpcs((uint*)p->context->ebp+2, pc);
58-
for(i=0; i<10 && pc[i] != 0; i++)
59-
cprintf(" %p", pc[i]);
60-
}
61-
cprintf("\n");
62-
}
63-
}
64-
65-
6628
//PAGEBREAK: 32
6729
// Look in the process table for an UNUSED proc.
6830
// If found, change state to EMBRYO and initialize
@@ -447,3 +409,41 @@ kill(int pid)
447409
return -1;
448410
}
449411

412+
//PAGEBREAK: 36
413+
// Print a process listing to console. For debugging.
414+
// Runs when user types ^P on console.
415+
// No lock to avoid wedging a stuck machine further.
416+
void
417+
procdump(void)
418+
{
419+
static char *states[] = {
420+
[UNUSED] "unused",
421+
[EMBRYO] "embryo",
422+
[SLEEPING] "sleep ",
423+
[RUNNABLE] "runble",
424+
[RUNNING] "run ",
425+
[ZOMBIE] "zombie"
426+
};
427+
int i;
428+
struct proc *p;
429+
char *state;
430+
uint pc[10];
431+
432+
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
433+
if(p->state == UNUSED)
434+
continue;
435+
if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
436+
state = states[p->state];
437+
else
438+
state = "???";
439+
cprintf("%d %s %s", p->pid, state, p->name);
440+
if(p->state == SLEEPING){
441+
getcallerpcs((uint*)p->context->ebp+2, pc);
442+
for(i=0; i<10 && pc[i] != 0; i++)
443+
cprintf(" %p", pc[i]);
444+
}
445+
cprintf("\n");
446+
}
447+
}
448+
449+

runoff.list

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ proc.h
2222
proc.c
2323
swtch.S
2424
kalloc.c
25+
data.S
2526
vm.c
2627
# system calls
2728
traps.h
@@ -48,6 +49,7 @@ exec.c
4849
# pipes
4950
pipe.c
5051

52+
5153
# string operations
5254
string.c
5355

@@ -62,6 +64,7 @@ kbd.c
6264
console.c
6365
timer.c
6466
uart.c
67+
multiboot.S
6568

6669
# user-level
6770
initcode.S
@@ -72,3 +75,4 @@ sh.c
7275

7376

7477

78+

0 commit comments

Comments
 (0)