diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/amd64/amd64/proc_machdep.c | 3 | ||||
-rw-r--r-- | sys/dev/cons/cons.c | 28 | ||||
-rw-r--r-- | sys/dev/cons/cons_ansi.c | 3 | ||||
-rw-r--r-- | sys/dev/ic/ahci.c | 3 | ||||
-rw-r--r-- | sys/dev/pci/pci.c | 77 | ||||
-rw-r--r-- | sys/fs/initramfs.c | 2 | ||||
-rw-r--r-- | sys/include/dev/acpi/tables.h | 30 | ||||
-rw-r--r-- | sys/include/dev/cons/cons.h | 1 | ||||
-rw-r--r-- | sys/include/dev/pci/pci.h | 1 | ||||
-rw-r--r-- | sys/include/sys/limits.h | 1 | ||||
-rw-r--r-- | sys/include/sys/proc.h | 2 | ||||
-rw-r--r-- | sys/include/sys/spawn.h | 2 | ||||
-rw-r--r-- | sys/kern/exec_elf64.c | 1 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 7 | ||||
-rw-r--r-- | sys/kern/kern_spawn.c | 53 | ||||
-rw-r--r-- | sys/vm/vm_physmem.c | 33 |
17 files changed, 201 insertions, 48 deletions
diff --git a/sys/arch/amd64/amd64/proc_machdep.c b/sys/arch/amd64/amd64/proc_machdep.c index 407adb1..aa8847a 100644 --- a/sys/arch/amd64/amd64/proc_machdep.c +++ b/sys/arch/amd64/amd64/proc_machdep.c @@ -40,7 +40,7 @@ #include <vm/map.h> #include <string.h> -void +uintptr_t md_td_stackinit(struct proc *td, void *stack_top, struct exec_prog *prog) { uintptr_t *sp = stack_top; @@ -97,6 +97,7 @@ md_td_stackinit(struct proc *td, void *stack_top, struct exec_prog *prog) STACK_PUSH(sp, argc); tfp = &td->tf; tfp->rsp = (uintptr_t)sp - VM_HIGHER_HALF; + return tfp->rsp; } void diff --git a/sys/dev/cons/cons.c b/sys/dev/cons/cons.c index ce2b154..0735f11 100644 --- a/sys/dev/cons/cons.c +++ b/sys/dev/cons/cons.c @@ -65,7 +65,6 @@ static struct cdevsw cons_cdevsw; static void cons_draw_cursor(struct cons_screen *scr, uint32_t color); static int cons_handle_special(struct cons_screen *scr, char c); -static void cons_clear_scr(struct cons_screen *scr, uint32_t bg); static uint32_t rgb_invert(uint32_t rgb) @@ -191,22 +190,14 @@ cons_handle_special(struct cons_screen *scr, char c) SHOW_CURSOR(scr); return 0; case ASCII_LF: - HIDE_CURSOR(scr); - /* Are we past screen width? */ if (scr->ch_row >= scr->nrows - 1) { cons_clear_scr(scr, scr->bg); - cons_flush(scr); - scr->ch_col = 0; - scr->ch_row = 0; - - /* Update cursor */ - scr->curs_row = 0; - scr->curs_col = 0; - SHOW_CURSOR(scr); return 0; } + HIDE_CURSOR(scr); + /* Make a newline */ cons_flush(scr); ++scr->ch_row; @@ -255,18 +246,25 @@ cons_draw_cursor(struct cons_screen *scr, uint32_t color) * @scr: Screen to clear. * @bg: Color to clear it to. */ -static void +void cons_clear_scr(struct cons_screen *scr, uint32_t bg) { struct fbdev fbdev = scr->fbdev; - struct cons_buf *bp; + + cons_flush(scr); + HIDE_CURSOR(scr); + + scr->ch_col = 0; + scr->ch_row = 0; + scr->curs_col = 0; + scr->curs_row = 0; for (size_t i = 0; i < fbdev.height * fbdev.pitch; ++i) { scr->fb_mem[i] = bg; } - bp = scr->ob[scr->nrows - 1]; - bp->flags |= CONS_BUF_CLEAN; + SHOW_CURSOR(scr); + } /* diff --git a/sys/dev/cons/cons_ansi.c b/sys/dev/cons/cons_ansi.c index 4403f9c..ab1f22a 100644 --- a/sys/dev/cons/cons_ansi.c +++ b/sys/dev/cons/cons_ansi.c @@ -90,8 +90,7 @@ ansi_feed(struct ansi_state *statep, char c) return c; case 2: if (c == 'H') { - cons_reset_cursor(&g_root_scr); - ansi_reset(statep); + cons_clear_scr(&g_root_scr, g_root_scr.bg); return ANSI_UPDATE_CURSOR; } break; diff --git a/sys/dev/ic/ahci.c b/sys/dev/ic/ahci.c index 7d89dd3..d8d4a6f 100644 --- a/sys/dev/ic/ahci.c +++ b/sys/dev/ic/ahci.c @@ -806,8 +806,6 @@ ahci_init_port(struct ahci_hba *hba, uint32_t portno) } dp->fra = PHYS_TO_VIRT(fra); - memset(dp->cmdlist, 0, clen * pagesz); - memset(dp->fra, 0, pagesz); /* Write the command list */ lo = cmdlist & 0xFFFFFFFF; @@ -826,7 +824,6 @@ ahci_init_port(struct ahci_hba *hba, uint32_t portno) tmp = vm_alloc_frame(1); dp->cmdlist[i].prdtl = 1; dp->cmdlist[i].ctba = tmp; - memset(PHYS_TO_VIRT(tmp), 0, pagesz); } mmio_write32(&port->serr, 0xFFFFFFFF); diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 95fc5e2..9dfb90e 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -32,20 +32,31 @@ #include <sys/syslog.h> #include <sys/errno.h> #include <sys/spinlock.h> +#include <sys/mmio.h> #include <dev/pci/pci.h> #include <dev/pci/pciregs.h> +#include <dev/acpi/acpi.h> +#include <dev/acpi/tables.h> #include <machine/pci/pci.h> #include <vm/dynalloc.h> +#include <vm/vm.h> #include <lib/assert.h> #define pr_trace(fmt, ...) kprintf("pci: " fmt, ##__VA_ARGS__) static TAILQ_HEAD(, pci_device) device_list; static struct spinlock devlist_lock = {0}; +static struct acpi_mcfg *mcfg; struct cam_hook { + /* PCI CAM */ pcireg_t(*cam_readl)(struct pci_device *dev, uint32_t off); void(*cam_writel)(struct pci_device *dev, uint32_t off, pcireg_t val); + + /* PCIe ECAM */ + pcireg_t(*ecam_readl)(struct pci_device *dev, uint32_t off); + void(*ecam_writel)(struct pci_device *dev, uint32_t off, pcireg_t val); + void *ecam_base[1]; } cam_hook = { NULL }; static bool @@ -129,6 +140,9 @@ pci_set_device_info(struct pci_device *dev) dev->prog_if = PCIREG_PROGIF(classrev); dev->hdr_type = (uint8_t)pci_readl(dev, PCIREG_HDRTYPE); + /* This is a PCIe device if it has CAP ID of 0x10 */ + dev->pci_express = pci_get_cap(dev, 0x10) != 0; + /* Set type-specific data */ switch (dev->hdr_type & ~BIT(7)) { case PCI_HDRTYPE_NORMAL: @@ -157,6 +171,53 @@ pci_set_device_info(struct pci_device *dev) static void pci_scan_bus(uint8_t bus); +static inline vaddr_t +pcie_ecam_addr(struct pci_device *dev) +{ + vaddr_t base = (vaddr_t)cam_hook.ecam_base[0]; + + base += dev->bus << 20 | + dev->slot << 15 | + dev->func << 12; + return base; +} + +static pcireg_t +pcie_ecam_readl(struct pci_device *dev, uint32_t offset) +{ + vaddr_t address; + + address = pcie_ecam_addr(dev); + address += (offset & ~3); + return mmio_read32((void *)address); +} + +static void +pcie_ecam_writel(struct pci_device *dev, uint32_t offset, pcireg_t val) +{ + vaddr_t address; + + address = pcie_ecam_addr(dev); + address += (offset & ~3); + mmio_write32((void *)address, val); +} + +static int +pcie_init(struct acpi_mcfg_base *base) +{ + void *iobase; + + pr_trace("[group %02d] @ bus [%02d - %02d]\n", base->seg_grpno, + base->bus_start, base->bus_end); + pr_trace("ecam @ %p\n", base->base_pa); + + iobase = PHYS_TO_VIRT(base->base_pa); + cam_hook.ecam_base[0] = iobase; + cam_hook.ecam_writel = pcie_ecam_writel; + cam_hook.ecam_readl = pcie_ecam_readl; + return 0; +} + /* * Attempt to register a device. * @@ -283,8 +344,10 @@ pci_add_device(struct pci_device *dev) pcireg_t pci_readl(struct pci_device *dev, uint32_t offset) { - if (cam_hook.cam_readl == NULL) { - return (pcireg_t)-1; + bool have_ecam = cam_hook.ecam_readl != NULL; + + if (dev->pci_express && have_ecam) { + return cam_hook.ecam_readl(dev, offset); } return cam_hook.cam_readl(dev, offset); @@ -293,7 +356,10 @@ pci_readl(struct pci_device *dev, uint32_t offset) void pci_writel(struct pci_device *dev, uint32_t offset, pcireg_t val) { - if (cam_hook.cam_writel == NULL) { + bool have_ecam = cam_hook.ecam_writel != NULL; + + if (dev->pci_express && have_ecam) { + cam_hook.ecam_writel(dev, offset, val); return; } @@ -306,6 +372,11 @@ pci_init(void) size_t ndev; TAILQ_INIT(&device_list); + mcfg = acpi_query("MCFG"); + if (mcfg != NULL) { + pcie_init(&mcfg->base[0]); + } + cam_hook.cam_readl = md_pci_readl; cam_hook.cam_writel = md_pci_writel; diff --git a/sys/fs/initramfs.c b/sys/fs/initramfs.c index b12a64b..c3f9b14 100644 --- a/sys/fs/initramfs.c +++ b/sys/fs/initramfs.c @@ -223,6 +223,8 @@ initramfs_read(struct vnode *vp, struct sio_txn *sio) return -EIO; if (sio->buf == NULL) return -EIO; + if (sio->len > n->size) + sio->len = n->size; src = n->data; dest = sio->buf; diff --git a/sys/include/dev/acpi/tables.h b/sys/include/dev/acpi/tables.h index 5215c86..d190150 100644 --- a/sys/include/dev/acpi/tables.h +++ b/sys/include/dev/acpi/tables.h @@ -132,4 +132,34 @@ struct __packed acpi_hpet { uint8_t page_protection; }; +/* + * PCIe / ACPI MCFG base address description + * table. + * + * @base_pa: Enhanced configuration base [physical] + * @seg_grpno: PCI segment group number + * @bus_start: Host bridge bus start + * @bus_end: Host bridge bus end + */ +struct __packed acpi_mcfg_base { + uint64_t base_pa; + uint16_t seg_grpno; + uint8_t bus_start; + uint8_t bus_end; + uint32_t reserved; +}; + +/* + * PCIe / ACPI MCFG structure + * + * @hdr: ACPI header + * @reserved: Do not use + * @base: ECAM MMIO address list + */ +struct __packed acpi_mcfg { + struct acpi_header hdr; + uint32_t reserved[2]; + struct acpi_mcfg_base base[1]; +}; + #endif /* _ACPI_TABLES_H_ */ diff --git a/sys/include/dev/cons/cons.h b/sys/include/dev/cons/cons.h index 9868493..7599dd5 100644 --- a/sys/include/dev/cons/cons.h +++ b/sys/include/dev/cons/cons.h @@ -67,6 +67,7 @@ struct cons_screen { void cons_init(void); void cons_expose(void); void cons_update_color(struct cons_screen *scr, uint32_t fg, uint32_t bg); +void cons_clear_scr(struct cons_screen *scr, uint32_t bg); void cons_reset_color(struct cons_screen *scr); void cons_reset_cursor(struct cons_screen *scr); int cons_putch(struct cons_screen *scr, char c); diff --git a/sys/include/dev/pci/pci.h b/sys/include/dev/pci/pci.h index a4de162..144b500 100644 --- a/sys/include/dev/pci/pci.h +++ b/sys/include/dev/pci/pci.h @@ -62,6 +62,7 @@ struct pci_device { uint8_t pci_subclass; uint8_t prog_if; uint8_t hdr_type; + uint8_t pci_express : 1; uint8_t pri_bus; uint8_t sec_bus; diff --git a/sys/include/sys/limits.h b/sys/include/sys/limits.h index 198c963..f56958e 100644 --- a/sys/include/sys/limits.h +++ b/sys/include/sys/limits.h @@ -32,6 +32,7 @@ #define PATH_MAX 1024 #define SSIZE_MAX 32767 +#define ARG_MAX 4096 #define CHAR_BIT 8 #if defined(_KERNEL) #define CPU_MAX 256 diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h index 2f1470a..241d990 100644 --- a/sys/include/sys/proc.h +++ b/sys/include/sys/proc.h @@ -95,7 +95,7 @@ int md_spawn(struct proc *p, struct proc *parent, uintptr_t ip); scret_t sys_spawn(struct syscall_args *scargs); pid_t spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **newprocp); -void md_td_stackinit(struct proc *td, void *stack_top, struct exec_prog *prog); +uintptr_t md_td_stackinit(struct proc *td, void *stack_top, struct exec_prog *prog); __dead void md_td_kick(struct proc *td); int fork1(struct proc *cur, int flags, void(*ip)(void), struct proc **newprocp); diff --git a/sys/include/sys/spawn.h b/sys/include/sys/spawn.h index 9d823db..0c54e4c 100644 --- a/sys/include/sys/spawn.h +++ b/sys/include/sys/spawn.h @@ -36,6 +36,6 @@ #define SPAWN_WAIT BIT(0) #if !defined(_KERNEL) -pid_t spawn(const char *pathname, int flags); +pid_t spawn(const char *pathname, char **argv, char **envp, int flags); #endif /* _KERNEL */ #endif /* !_SYS_SPAWN_H_ */ diff --git a/sys/kern/exec_elf64.c b/sys/kern/exec_elf64.c index 3767b0b..987dda4 100644 --- a/sys/kern/exec_elf64.c +++ b/sys/kern/exec_elf64.c @@ -192,6 +192,7 @@ elf64_load(const char *pathname, struct proc *td, struct exec_prog *prog) if ((status = elf64_verify(hdr)) != 0) goto done; + memset(loadmap, 0, sizeof(loadmap)); pcbp = &td->pcb; start = -1; end = 0; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index b760912..2a53b8a 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -101,7 +101,7 @@ execve(struct proc *td, const struct execve_args *args) stack_top = td->stack_base + (PROC_STACK_SIZE - 1); /* Setup registers, signals and stack */ - md_td_stackinit(td, (void *)(stack_top + VM_HIGHER_HALF), &prog); + stack_top = md_td_stackinit(td, (void *)(stack_top + VM_HIGHER_HALF), &prog); setregs(td, &prog, stack_top); signals_init(td); diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 6afae81..2f9e344 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -137,6 +137,10 @@ exit1(struct proc *td, int flags) proc_reap(td); } + if (td->data != NULL) { + dynfree(td->data); + } + /* * Only free the process structure if we aren't * being waited on, otherwise let it be so the @@ -157,8 +161,6 @@ exit1(struct proc *td, int flags) ci->curtd = NULL; if (parent->pid == 0) sched_enter(); - if (td->data == NULL) - sched_enter(); parent->flags &= ~PROC_SLEEP; sched_enter(); @@ -175,7 +177,6 @@ sys_exit(struct syscall_args *scargs) { struct proc *td = this_td(); - td->data = scargs->tf; td->exit_status = scargs->arg0; exit1(td, 0); __builtin_unreachable(); diff --git a/sys/kern/kern_spawn.c b/sys/kern/kern_spawn.c index 60d8e22..a953a6e 100644 --- a/sys/kern/kern_spawn.c +++ b/sys/kern/kern_spawn.c @@ -45,10 +45,17 @@ #define pr_trace(fmt, ...) kprintf("spawn: " fmt, ##__VA_ARGS__) #define pr_error(...) pr_trace(__VA_ARGS__) +#define ARGVP_MAX (ARG_MAX / sizeof(void *)) + static volatile size_t nthreads = 0; +/* + * TODO: envp + */ struct spawn_args { char path[PATH_MAX]; + char argv_blk[ARG_MAX]; + char *argv[ARGVP_MAX]; }; static inline void @@ -67,7 +74,6 @@ spawn_thunk(void) struct proc *cur; struct execve_args execve_args; struct spawn_args *args; - char *argv[] = { NULL, NULL }; char *envp[] = { NULL }; cur = this_td(); @@ -76,13 +82,10 @@ spawn_thunk(void) memset(pathbuf, 0, sizeof(pathbuf)); memcpy(pathbuf, path, strlen(path)); - argv[0] = (char *)pathbuf; - execve_args.pathname = argv[0]; - execve_args.argv = argv; + execve_args.pathname = pathbuf; + execve_args.argv = (char **)&args->argv[0]; execve_args.envp = envp; - path = NULL; - dynfree(args); if (execve(cur, &execve_args) != 0) { pr_error("execve failed, aborting\n"); @@ -211,19 +214,26 @@ get_child(struct proc *cur, pid_t pid) /* * arg0: The file /path/to/executable - * arg1: Optional flags (`flags') + * arg1: Argv + * arg2: Envp (TODO) + * arg3: Optional flags (`flags') */ scret_t sys_spawn(struct syscall_args *scargs) { struct spawn_args *args; - const char *u_path; + char *path; + const char *u_path, **u_argv; + const char *u_p = NULL; struct proc *td; int flags, error; + size_t len, bytes_copied = 0; + size_t argv_i = 0; td = this_td(); - flags = scargs->arg1; u_path = (const char *)scargs->arg0; + u_argv = (const char **)scargs->arg1; + flags = scargs->arg3; args = dynalloc(sizeof(*args)); if (args == NULL) { @@ -236,5 +246,30 @@ sys_spawn(struct syscall_args *scargs) return error; } + memset(args->argv, 0, ARG_MAX); + for (size_t i = 0; i < ARG_MAX - 1; ++i) { + error = copyin(&u_argv[argv_i], &u_p, sizeof(u_p)); + if (error < 0) { + dynfree(args); + return error; + } + if (u_p == NULL) { + args->argv[argv_i++] = NULL; + break; + } + + path = &args->argv_blk[i]; + error = copyinstr(u_p, path, ARG_MAX - bytes_copied); + if (error < 0) { + dynfree(args); + return error; + } + + args->argv[argv_i++] = &args->argv_blk[i]; + len = strlen(path); + bytes_copied += (len + 1); + i += len; + } + return spawn(td, spawn_thunk, args, flags, NULL); } diff --git a/sys/vm/vm_physmem.c b/sys/vm/vm_physmem.c index ed9b5d2..89f9ee6 100644 --- a/sys/vm/vm_physmem.c +++ b/sys/vm/vm_physmem.c @@ -36,11 +36,12 @@ #include <vm/vm.h> #include <string.h> -size_t highest_frame_idx = 0; -size_t bitmap_size = 0; -size_t bitmap_free_start = 0; +static size_t highest_frame_idx = 0; +static size_t bitmap_size = 0; +static size_t bitmap_free_start = 0; +static ssize_t last_idx = 0; -uint8_t *bitmap; +static uint8_t *bitmap; static struct limine_memmap_response *resp = NULL; static struct spinlock lock = {0}; @@ -137,15 +138,14 @@ physmem_init_bitmap(void) * * @count: Number of frames to allocate. */ -uintptr_t -vm_alloc_frame(size_t count) +static uintptr_t +__vm_alloc_frame(size_t count) { size_t frames = 0; ssize_t idx = -1; uintptr_t ret = 0; - spinlock_acquire(&lock); - for (size_t i = 0; i < highest_frame_idx; ++i) { + for (size_t i = last_idx; i < highest_frame_idx; ++i) { if (!testbit(bitmap, i)) { if (idx < 0) idx = i; @@ -167,9 +167,24 @@ vm_alloc_frame(size_t count) for (size_t i = idx; i < idx + count; ++i) { setbit(bitmap, i); } - ret = idx * DEFAULT_PAGESIZE; + last_idx = idx; + memset(PHYS_TO_VIRT(ret), 0, count * DEFAULT_PAGESIZE); done: + return ret; +} + +uintptr_t +vm_alloc_frame(size_t count) +{ + uintptr_t ret; + + spinlock_acquire(&lock); + if ((ret = __vm_alloc_frame(count)) == 0) { + last_idx = 0; + ret = __vm_alloc_frame(count); + } + spinlock_release(&lock); return ret; } |