Initial commit: Schunix as it stands before the SchOS rename
An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
This commit is contained in:
commit
d0f7acf9eb
275 changed files with 51417 additions and 0 deletions
466
include/defs.h
Normal file
466
include/defs.h
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
#pragma once
|
||||
|
||||
struct buf;
|
||||
struct context;
|
||||
struct file;
|
||||
struct inode;
|
||||
struct pipe;
|
||||
struct proc;
|
||||
struct rtcdate;
|
||||
struct spinlock;
|
||||
struct sleeplock;
|
||||
struct stat;
|
||||
struct superblock;
|
||||
struct trapframe;
|
||||
struct dirent;
|
||||
|
||||
// entryother.S / syscall.S
|
||||
void syscall_entry(void);
|
||||
void ignore_sysret(void);
|
||||
|
||||
// bio.c
|
||||
void binit(void);
|
||||
struct buf* bread(uint, uint);
|
||||
void brelse(struct buf*);
|
||||
void bwrite(struct buf*);
|
||||
|
||||
// console.c
|
||||
struct termios;
|
||||
void consoleinit(void);
|
||||
extern int tty_fg_pgrp;
|
||||
// The terminal's line-discipline settings. TCGETS/TCSETS in sys_fs.c are the
|
||||
// only callers; the console honours ICANON, ECHO, ECHOE, ECHONL, ISIG,
|
||||
// ICRNL, INLCR, IGNCR, ISTRIP and VMIN.
|
||||
void cons_get_termios(struct termios *);
|
||||
void cons_set_termios(const struct termios *);
|
||||
void cprintf(char*, ...);
|
||||
void consoleintr(int(*)(void));
|
||||
void panic(char*) __attribute__((noreturn));
|
||||
|
||||
// exec.c
|
||||
int exec(char*, char**);
|
||||
|
||||
// file.c
|
||||
struct file* filealloc(void);
|
||||
int fdalloc(struct file*);
|
||||
void fileclose(struct file*);
|
||||
struct file* filedup(struct file*);
|
||||
void fileinit(void);
|
||||
int fileread(struct file*, char*, int n);
|
||||
int file_poll(struct file*, int events);
|
||||
int filestat(struct file*, struct stat*);
|
||||
int filewrite(struct file*, char*, int n);
|
||||
|
||||
// fs.c
|
||||
void fsinit(int);
|
||||
int dirlink(struct inode*, char*, uint64);
|
||||
struct inode* dirlookup(struct inode*, char*, uint*);
|
||||
// Remove the entry `name` at the cookie dirlookup returned in *poff.
|
||||
int dirunlink(struct inode*, char*, uint);
|
||||
// 1 if the directory holds no real entries, 0 if it does, -1 on error.
|
||||
int dirempty(struct inode*);
|
||||
// Fill `out` with getdents64 records starting at *poff, which is an opaque
|
||||
// position the filesystem advances. Returns bytes written, 0 at end of
|
||||
// directory. The inode must be locked.
|
||||
int getdents(struct inode*, char *out, int cap, uint64 *poff);
|
||||
// Mount table: a substitution applied during path resolution. Nothing on disk
|
||||
// records a mount, so unmounting is forgetting.
|
||||
void mountinit(void);
|
||||
int mount_add(uint dev, uint64 inum, uint fsdev, uint64 root);
|
||||
int mount_del_by_root(uint fsdev, uint64 root);
|
||||
struct inode* ialloc(uint, short);
|
||||
struct inode* iget(uint, uint64);
|
||||
struct inode* idup(struct inode*);
|
||||
void iinit(void);
|
||||
void ilock(struct inode*);
|
||||
void iput(struct inode*);
|
||||
void iunlock(struct inode*);
|
||||
void iunlockput(struct inode*);
|
||||
void iupdate(struct inode*);
|
||||
int namecmp(const char*, const char*);
|
||||
struct inode* namei(char*);
|
||||
struct inode* nameiparent(char*, char*);
|
||||
struct inode* nameifrom(struct inode*, char*);
|
||||
struct inode* nameiparentfrom(struct inode*, char*, char*);
|
||||
int readi(struct inode*, int, uint64, uint64, uint);
|
||||
void stati(struct inode*, struct stat*);
|
||||
int writei(struct inode*, int, uint64, uint64, uint);
|
||||
void itrunc(struct inode*);
|
||||
void itrunc_to(struct inode*, uint64);
|
||||
unsigned int BKDRHash(char * str);
|
||||
uint tree_expand(struct inode *ip, uint off);
|
||||
void tree_search(struct inode* dp, char* name, uint* poff, struct dirent* de,uint add);
|
||||
void build_dir_tree(struct inode* dp,uint64 pinum);
|
||||
struct inode* divesymlink(struct inode *);
|
||||
void readsb(int dev, struct superblock *sb);
|
||||
|
||||
// pci.c -- bus enumeration. Drivers that need to *find* their hardware use
|
||||
// these; drivers for things that have lived at a fixed address since 1984
|
||||
// (the PIC, the PIT, the legacy IDE ports) do not.
|
||||
struct pci_dev;
|
||||
struct pci_driver;
|
||||
void pci_init(void);
|
||||
uint32 pci_read32(uint8, uint8, uint8, uint8);
|
||||
uint16 pci_read16(uint8, uint8, uint8, uint8);
|
||||
uint8 pci_read8(uint8, uint8, uint8, uint8);
|
||||
void pci_write32(uint8, uint8, uint8, uint8, uint32);
|
||||
void pci_enable(struct pci_dev *, uint16 bits);
|
||||
uint8 pci_find_cap(struct pci_dev *, uint8 id);
|
||||
int pci_msi_enable(struct pci_dev *, int vector, int cpu);
|
||||
int pci_count(void);
|
||||
struct pci_dev *pci_get(int);
|
||||
struct pci_dev *pci_find_class(uint8 class, uint8 subclass);
|
||||
struct pci_dev *pci_find_id(uint16 vendor, uint16 device);
|
||||
void pci_bind(const struct pci_driver *);
|
||||
int pci_info(char *buf, int cap);
|
||||
|
||||
// drivers/registry.c -- the one list of every driver in the kernel.
|
||||
void pci_bind_all(void);
|
||||
|
||||
// xhci.c — `echo u > /proc/sysrq`
|
||||
void xhci_dump(void);
|
||||
|
||||
// ide.c
|
||||
void ideinit(void);
|
||||
void ideintr(void);
|
||||
void iderw(struct buf*);
|
||||
// For probes, not for reads: iderw() panics on an absent drive, so anything
|
||||
// that is guessing whether a disk exists has to ask here first.
|
||||
int ide_disk_present(int dev);
|
||||
|
||||
// fs/schfs/kmount.c -- SchFS.
|
||||
//
|
||||
// Objects are named by 64-bit object id, not by a path: resolution is the
|
||||
// caller's business, so these compose with a VFS rather than assuming one.
|
||||
// Every schfs_k* that changes anything is one transaction and is durable by the
|
||||
// time it returns.
|
||||
struct schfs_inode;
|
||||
void schfs_kmount(uint dev);
|
||||
int schfs_kmounted(void);
|
||||
uint64 schfs_klookup(const char *path);
|
||||
int schfs_kstat(uint64 ino, struct schfs_inode *out);
|
||||
long schfs_kread(uint64 ino, uint64 off, void *buf, unsigned n);
|
||||
int schfs_kreaddir(uint64 dir,
|
||||
int (*fn)(uint64, unsigned short, const char *,
|
||||
unsigned, void *),
|
||||
void *arg);
|
||||
int schfs_kinfo(char *buf, int cap);
|
||||
|
||||
int schfs_kcreate(uint64 dir, const char *name, unsigned namelen,
|
||||
unsigned short type, uint mode,
|
||||
unsigned short major, unsigned short minor, uint64 *out);
|
||||
long schfs_kwrite(uint64 ino, uint64 off, const void *buf,
|
||||
unsigned n);
|
||||
int schfs_ktruncate(uint64 ino, uint64 size);
|
||||
int schfs_kunlink(uint64 dir, const char *name, unsigned namelen);
|
||||
int schfs_klink(uint64 dir, const char *name, unsigned namelen,
|
||||
uint64 ino);
|
||||
int schfs_krename(uint64 olddir, const char *oldname,
|
||||
unsigned oldlen, uint64 newdir, const char *newname,
|
||||
unsigned newlen);
|
||||
int schfs_ksetattr(uint64 ino, const struct schfs_inode *in);
|
||||
int schfs_ksync(void);
|
||||
|
||||
// Pieces the VFS layer (fs/schfs/vfs.c) needs, where a directory entry and the
|
||||
// object it names are separate operations. The VFS keeps the link count.
|
||||
uint64 schfs_klookup_at(uint64 dir, const char *name, unsigned len);
|
||||
int schfs_kdirempty(uint64 dir);
|
||||
int schfs_kalloc_object(unsigned short type, uint mode,
|
||||
uint64 *out);
|
||||
int schfs_kdiradd(uint64 dir, const char *name, unsigned len,
|
||||
uint64 ino, unsigned short type);
|
||||
int schfs_kdirdel(uint64 dir, const char *name, unsigned len);
|
||||
int schfs_kfree(uint64 ino);
|
||||
uint64 schfs_kroot(void);
|
||||
|
||||
// ramdisk.c
|
||||
uint uptime(void);
|
||||
|
||||
// procfs.c
|
||||
int procread(struct inode*, uint, char*, int);
|
||||
int procwrite(struct inode*, uint, char*, int);
|
||||
// Shared with the /proc filesystem (kernel/fs/procfs.c): one owns the
|
||||
// namespace, the other the content.
|
||||
int proc_gen_global(int id, char *buf, int cap);
|
||||
int proc_write_sysrq(int user_src, uint64 src, uint n);
|
||||
void procfs_mount(void);
|
||||
|
||||
// input.c -- raw evdev event devices
|
||||
void inputinit(void);
|
||||
int inputread(struct inode*, uint, char*, int);
|
||||
int inputwrite(struct inode*, uint, char*, int);
|
||||
int inputready(struct inode*);
|
||||
void inputclose(struct inode*);
|
||||
void inputopen(struct inode*);
|
||||
int input_ioctl(struct inode*, int request, addr_t arg);
|
||||
int input_grab(int dev, int on);
|
||||
int input_is_grabbed(int dev);
|
||||
void input_report(int dev, int type, int code, int value);
|
||||
void input_sync(int dev);
|
||||
int input_ready(int dev);
|
||||
void input_ps2_scancode(int raw, int e0);
|
||||
void input_key(int hid_usage, int down);
|
||||
int input_hid_keycode(int hid_usage);
|
||||
void input_mouse(int dx, int dy, int buttons);
|
||||
|
||||
void ramdiskinit(void);
|
||||
void ramdiskrw(struct buf*);
|
||||
int ramdisk_present(void);
|
||||
|
||||
// usb_storage.c
|
||||
void usb_storage_rw(struct buf*);
|
||||
int usb_storage_present(void);
|
||||
void usb_storage_dump(void); // `echo s > /proc/sysrq`
|
||||
|
||||
// ioapic.c
|
||||
void ioapicenable(int irq, int cpu);
|
||||
void ioapicroute(int irq, int cpu, int level_low);
|
||||
void ioapicmask(int irq);
|
||||
extern uchar ioapicid;
|
||||
void ioapicinit(void);
|
||||
|
||||
// dma.c — see include/dma.h for the full contract
|
||||
void dma_init(void*, void*);
|
||||
void *dma_alloc(uint64 size, uint64 align);
|
||||
void dma_free(void*, uint64 size);
|
||||
addr_t dma_phys(const void*);
|
||||
uint64 dma_free_bytes(void);
|
||||
uint64 dma_total_bytes(void);
|
||||
|
||||
// kalloc.c
|
||||
char* kalloc(void);
|
||||
uint64 kalloc_free_bytes(void);
|
||||
void kfree(char*);
|
||||
void kinit1(void*, void*);
|
||||
void kinit2(void);
|
||||
|
||||
// kbd.c
|
||||
void kbdintr(void);
|
||||
|
||||
// mouse.c
|
||||
void mouseinit(void);
|
||||
void mouseintr(void);
|
||||
void mouse_inject(int dx, int dy, int buttons);
|
||||
int get_mouse_x(void);
|
||||
int get_mouse_y(void);
|
||||
uint8 get_mouse_buttons(void);
|
||||
|
||||
// lapic.c
|
||||
void cmostime(struct rtcdate *r);
|
||||
|
||||
// time.c -- wall-clock time, from the RTC read once at boot plus uptime.
|
||||
void time_init(void);
|
||||
void wallclock(uint64 *sec, uint64 *usec);
|
||||
extern uint64 boot_epoch;
|
||||
int cpunum(void);
|
||||
extern volatile uint* lapic;
|
||||
void lapiceoi(void);
|
||||
void lapicinit(void);
|
||||
void lapicstartap(uchar, uint);
|
||||
void microdelay(int);
|
||||
|
||||
// log.c
|
||||
void initlog(int dev);
|
||||
void log_write(struct buf*);
|
||||
void begin_op();
|
||||
void end_op();
|
||||
|
||||
// mp.c
|
||||
extern int ismp;
|
||||
void mpinit(void);
|
||||
|
||||
// pipe.c
|
||||
int pipealloc(struct file**, struct file**);
|
||||
void pipeclose(struct pipe*, int);
|
||||
int piperead(struct pipe*, char*, int);
|
||||
int pipewrite(struct pipe*, char*, int);
|
||||
|
||||
// net/unix.c
|
||||
struct socket;
|
||||
void sockinit(void);
|
||||
struct socket* socknew(int domain, int type);
|
||||
void sockclose(struct socket*);
|
||||
void sockdup(struct socket*);
|
||||
int sockread(struct socket*, char*, int);
|
||||
int sockwrite(struct socket*, char*, int);
|
||||
int sockbind(struct socket*, const char *path);
|
||||
int socklisten(struct socket*, int backlog);
|
||||
struct socket* sockaccept(struct socket*);
|
||||
int sockconnect(struct socket*, const char *path);
|
||||
int sockreadable(struct socket*);
|
||||
int sock_hup(struct socket*);
|
||||
int sock_shutdown(struct socket*, int how);
|
||||
int sockpair(struct socket **a, struct socket **b);
|
||||
const char* sockname(struct socket*);
|
||||
|
||||
// proc.c
|
||||
void exit(int status);
|
||||
int fork(void);
|
||||
int growproc(int64);
|
||||
int kill(int);
|
||||
int sigsend_pgrp(int pgid, int sig);
|
||||
int proc_pgid(int pid);
|
||||
int proc_setpgid(int pid, int pgid);
|
||||
int proc_setsid(void);
|
||||
int sigsend(int pid, int sig);
|
||||
int proc_exists(int);
|
||||
int proc_num(void);
|
||||
struct procinfo;
|
||||
int proc_snapshot(int idx, struct procinfo *out);
|
||||
int proc_snapshot_pid(int pid, struct procinfo *out);
|
||||
void pinit(void);
|
||||
void procdump(void);
|
||||
void scheduler(void) __attribute__((noreturn));
|
||||
void sched(void);
|
||||
void sleep(void*, struct spinlock*);
|
||||
int wait(void);
|
||||
int waitpid(int, int*, int);
|
||||
void wakeup(void*);
|
||||
void yield(void);
|
||||
void sinit(void);
|
||||
void kstack_check_canary(const char *where);
|
||||
|
||||
// swtch.S
|
||||
void swtch(struct context**, struct context*);
|
||||
|
||||
// spinlock.c
|
||||
void acquire(struct spinlock*);
|
||||
void getcallerpcs(void*, addr_t*);
|
||||
void getstackpcs(addr_t*, addr_t*);
|
||||
int holding(struct spinlock*);
|
||||
void initlock(struct spinlock*, char*);
|
||||
void release(struct spinlock*);
|
||||
void pushcli(void);
|
||||
void popcli(void);
|
||||
|
||||
// sleeplock.c
|
||||
void acquiresleep(struct sleeplock*);
|
||||
void releasesleep(struct sleeplock*);
|
||||
int holdingsleep(struct sleeplock*);
|
||||
void initsleeplock(struct sleeplock*, char*);
|
||||
|
||||
// string.c
|
||||
int memcmp(const void*, const void*, uint64);
|
||||
void* memmove(void*, const void*, uint64);
|
||||
void* memset(void*, int, uint64);
|
||||
char* safestrcpy(char*, const char*, int);
|
||||
int strlen(const char*);
|
||||
int strnlen(const char*, int);
|
||||
int strncmp(const char*, const char*, uint64);
|
||||
char* strncpy(char*, const char*, int);
|
||||
|
||||
// syscall.c
|
||||
void syscall(struct trapframe *);
|
||||
void syscallinit(void);
|
||||
void deliver_signals(struct trapframe *);
|
||||
int argint(int, int*);
|
||||
int argptr(int, char**, int);
|
||||
int argstr(int, char**);
|
||||
int argaddr(int, addr_t*);
|
||||
int fetchaddr(addr_t, addr_t*);
|
||||
int fetchstr(addr_t, char**);
|
||||
int fetchint(addr_t, int*);
|
||||
|
||||
// trap.c
|
||||
void idtinit(void);
|
||||
extern uint ticks;
|
||||
void tvinit(void);
|
||||
extern struct spinlock tickslock;
|
||||
|
||||
// uart.c
|
||||
void uartearlyinit(void);
|
||||
void uartinit(void);
|
||||
void uartintr(void);
|
||||
void uartputc(int);
|
||||
|
||||
// vga.c
|
||||
void vga_init(uint64);
|
||||
void vga_draw_pixel(int, int, uint32);
|
||||
void vga_draw_char(int, int, uchar, uint32);
|
||||
void vga_puts(int, int, char*, uint32);
|
||||
void vga_putc(int, uint32);
|
||||
void vga_clear(uint32);
|
||||
void vga_screen_reset(void);
|
||||
void vga_set_bg(uint32);
|
||||
// Crash-screen primitives: the panic handler lays itself out rather than
|
||||
// printing. See kernel/core/panic.c.
|
||||
int vga_ready(void);
|
||||
void vga_dims(int *w, int *h);
|
||||
int vga_char_w(void);
|
||||
int vga_char_h(void);
|
||||
// Framebuffer geometry. vga.c reads the VBE mode info, so it is the only
|
||||
// thing that knows where the framebuffer is; nobody else may assume.
|
||||
uint64 vga_fb_phys(void);
|
||||
uint64 vga_fb_size(void);
|
||||
uint32 vga_fb_stride(void);
|
||||
uint32 vga_fb_bpp(void);
|
||||
volatile uchar *vga_fb_ptr(void);
|
||||
|
||||
// fb.c -- /dev/fb0, major 2.
|
||||
void fbclose(struct inode*);
|
||||
// Called from sys_mmap: a mapping of /dev/fb0 is a licence to draw with no
|
||||
// further syscalls, so it is the last the kernel hears about it.
|
||||
void fb_mapped(void);
|
||||
int fbread(struct inode*, uint, char*, int);
|
||||
int fbwrite(struct inode*, uint, char*, int);
|
||||
int fb_ioctl(int request, addr_t arg);
|
||||
// drivers/net/e1000 -- raw Ethernet. No protocol stack above it yet, so these
|
||||
// are the whole interface: queue a frame, take a frame, and the MAC.
|
||||
int e1000_transmit(const void *frame, int len);
|
||||
int e1000_receive(void *out, int cap);
|
||||
const unsigned char *e1000_mac(void);
|
||||
void e1000_selftest(void);
|
||||
|
||||
// registry.c
|
||||
void platform_register_devices(void);
|
||||
|
||||
void e820_init(void);
|
||||
int acpi_init(void);
|
||||
void vga_fill_rect(int x, int y, int w, int h, uint32);
|
||||
void vga_fill_circle(int cx, int cy, int r, uint32);
|
||||
void vga_text_at(int, int, const char*, uint32);
|
||||
void vga_draw_logo(int x, int y, uint32 color, uint32 bg);
|
||||
void vga_logo_centered(int cy, uint32 color, uint32 bg);
|
||||
// Cursor addressing and erasing, for the console's ANSI escape parser.
|
||||
int vga_cols(void);
|
||||
int vga_rows(void);
|
||||
void vga_cursor_get(int *col, int *row);
|
||||
void vga_cursor_set(int col, int row);
|
||||
void vga_erase_display(int mode);
|
||||
void vga_erase_line(int mode);
|
||||
|
||||
// console.c / panic.c
|
||||
void cons_panic_mode(void);
|
||||
extern int cons_serial_only;
|
||||
void console_takeover(void);
|
||||
|
||||
// vm.c
|
||||
void seginit(void);
|
||||
void kvmalloc(void);
|
||||
pml4e_t* setupkvm(void);
|
||||
char* uva2ka(pml4e_t*, char*);
|
||||
addr_t allocuvm(pml4e_t*, uint64, uint64);
|
||||
addr_t deallocuvm(pml4e_t*, uint64, uint64);
|
||||
void freevm(pml4e_t*);
|
||||
void inituvm(pml4e_t*, char*, uint64);
|
||||
int loaduvm(pml4e_t*, char*, struct inode*, uint64, uint64);
|
||||
pml4e_t* copyuvm(pml4e_t*, uint64);
|
||||
void switchuvm(struct proc*);
|
||||
void switchkvm(void);
|
||||
int pipe_poll(struct pipe*, int readable, int writable);
|
||||
int console_input_ready(void);
|
||||
int copyin(pml4e_t*, addr_t, void*, uint64);
|
||||
int copyout(pml4e_t*, addr_t, void*, uint64);
|
||||
void vm_unmap_range(pml4e_t*, uint64, uint64);
|
||||
// Unmap without freeing: for pages this process does not own — device memory
|
||||
// and shared segments. vm_unmap_range() would hand them to kfree.
|
||||
void vm_unmap_norelease(pml4e_t*, uint64, uint64);
|
||||
// Shared memory (sys_mem.c). shm_ref/shm_detach maintain the attachment
|
||||
// count that decides when a segment's pages go back.
|
||||
void shm_ref(int id);
|
||||
void shm_detach(int id);
|
||||
void proc_release_shared(struct proc *);
|
||||
int copy_vma_range(pml4e_t *dstpgdir, pml4e_t *srcpgdir, uint64 va, uint64 length, int is_fb);
|
||||
void clearpteu(pml4e_t *pgdir, char *uva);
|
||||
|
||||
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
|
||||
Loading…
Reference in a new issue