Assignment 2 tips
1
The Basic ASST2 Spec
• Implement open(), read(), write(), lseek(), close(), and dup2()
• Not assuming a single process • Assume fork() exists
• User-level exists • asst2
• C libraries
• Anexistingframeworkandcodefor:
• system call dispatching, • VFS
• Emufs
• drivers
2
Overview
• Overall structure
• User-level
• Process structure
• In-kernel
• The storage stack
• Overview of VFS and emufs functionality
• Details
• Understanding the system interface
• Argument passing
• System call dispatching
• Moving data across the user-kernel boundary • Connecting the interface to the VFS
3
Structure of a Computer System
userland/testbin/asst2
Application
System Libraries
asst2.c
userland/lib/libc
User Mode Kernel Mode
Device Device
OS/161 kern
Memory
4
R3000 Address Space Layout
• ksegX not accessible in usermode
0xFFFFFFFF
0xC0000000 0xA0000000
0x80000000
• Switching processes switches the application view of memory (translation stored in a page table) for kuseg
0x00000000
kseg2
kseg1
kseg0
Proc 1 kuseg
Proc 2 kuseg
Proc 3 kuseg
5
Process Layout
• Where is asst2 code/data (from asst2.c)?
0xC0000000
0xA0000000
0x80000000
0xffffffff
0x10000000
0x04000000
0x00000000
Free RAM
OS/161 Kernel
stack
other?
data
code
6
Calling open()
int open(const char *filename,
int flags, …);
• Where is the function “open()”?
0xC0000000
0xA0000000
0x80000000
0xffffffff
0x10000000
0x04000000
0x00000000
Free RAM
OS/161 Kernel
stack
other?
data
code
7
Structure of a Computer System
Interaction via
System Calls
Application
System Libraries
User Mode Kernel Mode
Device Device
OS/161
Memory
8
OS/161 storage stack asst2
Application
Syscall dispatching
FD table
OF table
VFS
FS
Device driver
emufs
sys161
~/cs3231/root
9
open()?
int open(const char *filename,
int flags, …);
• Where is “open()’s” implementation?
• By convention, it’s called sys_open() in the
kernel.
This is what you are implementing in ASST2
0xC0000000
0xA0000000
0x80000000
0xffffffff
0x10000000
0x04000000
0x00000000
Free RAM
OS/161 Kernel
stack
other?
data
code
10
Existing storage stack asst2
Application
Syscall dispatching
FD table
OF table
VFS
FS
Device driver
emufs
sys161 sys161
~/cs3231/root
11
OS 161 root filesystem
Provided Storage Stack Host filesystem
VFS emufs driver sys161
12
Details
13
System Call Interface
int open(const char *filename, int flags);
int open(const char *filename, int flags, mode_t mode);
int close(int fd);
ssize_t read(int fd, void *buf, size_t buflen);
ssize_t write(int fd, const void *buf, size_t nbytes);
int dup2(int oldfd, int newfd);
off_t lseek(int fd, off_t pos, int whence);
Solution should work with fork() if implemented
pid_t fork(void);
14
open/close
int open(const char *filename, int flags);
int open(const char *filename, int flags, mode_t mode);
int close(int fd);
15
Read/write
ssize_t read(int fd, void *buf, size_t buflen);
ssize_t write(int fd, const void *buf, size_t nbytes);
16
dup2
int dup2(int oldfd, int newfd);
17
lseek
off_t lseek(int fd, off_t pos, int whence);
18
fork
pid_t fork(void);
19
Argument passing
#include
int reboot(int code);
Description
reboot reboots or shuts down the system. The specific action depends on the code passed:
RB_REBOOT The system is rebooted. RB_HALT The system is halted. RB_POWEROFF The system is powered off.
Return Values
On success, reboot does not return. On error, -1 is returned, and errno is set according to the error encountered.
20
ra
fp
sp
gp
k1
k0
s7
⁞
s0
t9
⁞
t0
a3
a2
a1
a0
v1
v0
AT
zero
Preserved
ra
fp
sp
gp
k1
k0
s7
⁞
s0
t9
⁞
t0
a3
a2
a1
a0
v1
v0
AT
zero
Convention for kernel entry
Preserved for C calling convention
Preserved
Success?
Args in
Result SysCall No.
Convention for kernel exit
21
struct trapframe {
u_int32_t tf_vaddr;
u_int32_t tf_status;
u_int32_t tf_cause;
u_int32_t tf_lo;
u_int32_t tf_hi;
u_int32_t tf_ra;
u_int32_t tf_at;
u_int32_t tf_v0;
u_int32_t tf_v1;
u_int32_t tf_a0;
u_int32_t tf_a1;
u_int32_t tf_a2;
u_int32_t tf_a3;
u_int32_t tf_t0;
⁞
u_int32_t tf_t7;
u_int32_t tf_s0;
⁞
u_int32_t tf_s7;
u_int32_t tf_t8;
u_int32_t tf_t9;
u_int32_t tf_k0;
*/
u_int32_t tf_k1;
u_int32_t tf_gp;
u_int32_t tf_sp;
u_int32_t tf_s8;
u_int32_t tf_epc;
};
/* vaddr register */
/* status register */
/* cause register */
/* Saved register 31 */
/* Saved register 1 (AT) */
/* Saved register 2 (v0) */
/* etc. */
By creating a pointer to here of type
struct trapframe *, we can access the
user’s saved registers as normal
Kernel Stack
epc
s8
sp
gp
k1
k0
t9
t8
⁞
at
ra
hi
lo
cause
status
vaddr
/* dummy (see exception.S comments)
variables within ‘C’
/* dummy */
/* coprocessor 0 epc register */
22
syscall(struct trapframe *tf)
{
callno = tf->tf_v0;
retval = 0;
switch (callno) {
case SYS_reboot:
err = sys_reboot(tf->tf_a0);
break;
/* Add stuff here */
default:
kprintf(“Unknown syscall %d\n”, callno); err = ENOSYS;
break;
}
23
if (err) {
tf->tf_v0 = err;
tf->tf_a3 = 1;
}
else {
/* Success. */
tf->tf_v0 = retval;
tf->tf_a3 = 0;
tf->tf_epc += 4;
}
/* signal an error */
}
/* signal no error */
24
System Call Interface
int open(const char *filename, int flags);
int open(const char *filename, int flags, mode_t mode);
int close(int fd);
ssize_t read(int fd, void *buf, size_t buflen);
ssize_t write(int fd, const void *buf, size_t nbytes);
int dup2(int oldfd, int newfd);
off_t lseek(int fd, off_t pos, int whence);
25
lseek() Offset
uint64_t offset;
int whence;
off_t retval64;
join32to64(tf->tf_a2, tf->tf_a3, &offset);
copyin((userptr_t)tf->tf_sp + 16, &whence, sizeof(int));
split64to32(retval64, &tf->tf_v0, &tf->tf_v1);
26
27
Pointers
• What about the first argument to open()
• It’sastring?
• What are the problems with accessing a string (i.e. user-specified region of memory)?
0xC0000000
0xA0000000
0x80000000
0xffffffff
0x10000000
0x04000000
0x00000000
Free RAM
OS/161 Kernel
stack
data
code
28
Copy in/out(str)
int copyin(const_userptr_t usersrc, void *dest, size_t len);
int copyout(const void *src, userptr_t userdest, size_t len);
int copyinstr(const_userptr_t usersrc, char *dest, size_t len, size_t *got);
int copyoutstr(const char *src, userptr_t userdest, size_t len, size_t *got);
0xC0000000
0xA0000000
0x80000000
0xffffffff
0x10000000
0x04000000
0x00000000
Free RAM
OS/161 Kernel
stack
data
code
29
Buffers – e.g. read()
• Kernel framework for safely handling buffers
• Does error/range/validity checking for you
ssize_t read(int fd, void *buf, size_t buflen);
0xC0000000
0xA0000000
0x80000000
struct iovec {
union {
};
userptr_t iov_ubase; void *iov_kbase;
/* user-supplied pointer */ /* kernel-supplied pointer */
};
size_t iov_len;
/* Length of data */
0xffffffff
0x10000000
0x04000000
0x00000000
Free RAM
OS/161 Kernel
stack
data
code
30
VFS READ
A macro with sanity checking
VOP_READ(vn, uio)
Invokes a function point of following prototype:
int (*vop_read)(struct vnode *file, struct uio *uio);
What are the arguments?
31
UIO
/* Source/destination. */
enum uio_seg {
UIO_USERISPACE,
UIO_USERSPACE,
UIO_SYSSPACE,
};
struct uio {
struct iovec
*uio_iov;
uio_iovcnt;
uio_offset;
uio_resid;
uio_segflg;
uio_rw;
/* User process code. */
/* User process data. */
/* Kernel. */
/* Data blocks */
/* Number of iovecs */
/* Desired offset into object */
/* Remaining amt of data to xfer */ /* What kind of pointer we have */ /* Whether op is a read or write */ /* Address space for user pointer */
};
unsigned
off_t
size_t
enum uio_seg
enum uio_rw
struct addrspace *uio_space;
32
Sample Helper function
uio_uinit(struct iovec *iov, struct uio *u, userptr_t buf,
size_t len, off_t offset, enum uio_rw rw)
{
iov->iov_ubase = buf;
iov->iov_len = len;
u->uio_iov = iov;
u->uio_iovcnt = 1;
u->uio_offset = offset;
u->uio_resid = len;
u->uio_segflg = UIO_USERSPACE;
u->uio_rw = rw;
u->uio_space = proc_getas();
}
33
System call implementation
1. sys_open() 2. sys_close() 3. sys_read() 4. sys_write() 5. sys_lseek() 6. sys_dup2()
1. vfs_open()
• copyinstr()
2. vfs_close()
3. VOP_READ()
4. VOP_WRITE()
5. VOP_ISSEEKABLE() 6. VOP_STAT()
34