summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/aarch64/aarch64/pmap.c21
-rw-r--r--sys/arch/amd64/amd64/intr.c7
-rw-r--r--sys/arch/amd64/amd64/machdep.c52
-rw-r--r--sys/arch/amd64/amd64/mp.c28
-rw-r--r--sys/arch/amd64/amd64/pmap.c36
-rw-r--r--sys/arch/amd64/amd64/proc_machdep.c23
-rw-r--r--sys/arch/amd64/amd64/vector.S126
-rw-r--r--sys/dev/usb/xhci.c12
-rw-r--r--sys/include/arch/amd64/cdefs.h9
-rw-r--r--sys/include/arch/amd64/cpu.h8
-rw-r--r--sys/include/sys/driver.h2
-rw-r--r--sys/include/sys/limits.h4
-rw-r--r--sys/include/sys/proc.h5
-rw-r--r--sys/include/sys/sched.h2
-rw-r--r--sys/include/sys/spawn.h3
-rw-r--r--sys/include/vm/pmap.h11
-rw-r--r--sys/kern/kern_descrip.c2
-rw-r--r--sys/kern/kern_exec.c2
-rw-r--r--sys/kern/kern_exit.c52
-rw-r--r--sys/kern/kern_sched.c67
-rw-r--r--sys/kern/kern_spawn.c26
21 files changed, 384 insertions, 114 deletions
diff --git a/sys/arch/aarch64/aarch64/pmap.c b/sys/arch/aarch64/aarch64/pmap.c
index b5ebda9..7e93959 100644
--- a/sys/arch/aarch64/aarch64/pmap.c
+++ b/sys/arch/aarch64/aarch64/pmap.c
@@ -66,3 +66,24 @@ pmap_destroy_vas(struct vas vas)
/* TODO: STUB */
return;
}
+
+bool
+pmap_is_clean(struct vas vas, vaddr_t va)
+{
+ /* TODO: STUB */
+ return false;
+}
+
+void
+pmap_mark_clean(struct vas vas, vaddr_t va)
+{
+ /* TODO: STUB */
+ return;
+}
+
+int
+pmap_set_cache(struct vas vas, vaddr_t va, int type)
+{
+ /* TODO: STUB */
+ return 0;
+}
diff --git a/sys/arch/amd64/amd64/intr.c b/sys/arch/amd64/amd64/intr.c
index 1529b1c..9f70e88 100644
--- a/sys/arch/amd64/amd64/intr.c
+++ b/sys/arch/amd64/amd64/intr.c
@@ -96,11 +96,12 @@ intr_register(const char *name, const struct intr_hand *ih)
* Try to allocate an interrupt vector. An IPL is made up
* of 4 bits so there can be 16 vectors per IPL.
*
- * XXX: Vector 0x20 is reserved for the Hyra scheduler and
- * vector 0x21 is reserved for the CPU halt IPI.
+ * XXX: Vector 0x20 is reserved for the Hyra scheduler,
+ * vector 0x21 is reserved for the CPU halt IPI,
+ * and vector 0x22 is reserved for TLB shootdowns.
*/
for (int i = vec; i < vec + 16; ++i) {
- if (g_intrs[i] != NULL || i < 0x22) {
+ if (g_intrs[i] != NULL || i < 0x23) {
continue;
}
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index 3381437..c6fb6c4 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -42,9 +42,11 @@
#include <machine/uart.h>
#include <machine/sync.h>
#include <machine/intr.h>
+#include <machine/cdefs.h>
#include <machine/isa/i8042var.h>
#define HALT_VECTOR 0x21
+#define TLB_VECTOR 0x22
#if defined(__SPECTRE_IBRS)
#define SPECTRE_IBRS __SPECTRE_IBRS
@@ -52,8 +54,6 @@
#define SPECTRE_IBRS 0
#endif
-static uint8_t halt_vector = 0;
-
int ibrs_enable(void);
void syscall_isr(void);
void pin_isr_load(void);
@@ -68,6 +68,31 @@ cpu_halt_isr(void *p)
__builtin_unreachable();
}
+__attribute__((__interrupt__))
+static void
+tlb_shootdown_isr(void *p)
+{
+ struct cpu_info *ci;
+ int ipl;
+
+ /*
+ * Get the current CPU and check if we even
+ * need a shootdown. If `tlb_shootdown' is
+ * unset, this is not for us.
+ */
+ ci = this_cpu();
+ if (!ci->tlb_shootdown) {
+ return;
+ }
+
+ ipl = splraise(IPL_HIGH);
+ __invlpg(ci->shootdown_va);
+
+ ci->shootdown_va = 0;
+ ci->tlb_shootdown = 0;
+ splx(ipl);
+}
+
static void
setup_vectors(void)
{
@@ -85,6 +110,7 @@ setup_vectors(void)
idt_set_desc(0xE, IDT_TRAP_GATE, ISR(page_fault), 0);
idt_set_desc(0x80, IDT_USER_INT_GATE, ISR(syscall_isr), 0);
idt_set_desc(HALT_VECTOR, IDT_INT_GATE, ISR(cpu_halt_isr), 0);
+ idt_set_desc(TLB_VECTOR, IDT_INT_GATE, ISR(tlb_shootdown_isr), 0);
pin_isr_load();
}
@@ -130,6 +156,26 @@ backtrace_addr_to_name(uintptr_t addr, off_t *off)
}
void
+cpu_shootdown_tlb(vaddr_t va)
+{
+ uint32_t ncpu = cpu_count();
+ struct cpu_info *cip;
+
+ for (uint32_t i = 0; i < ncpu; ++i) {
+ cip = cpu_get(i);
+ if (cip == NULL) {
+ break;
+ }
+
+ spinlock_acquire(&cip->lock);
+ cip->shootdown_va = va;
+ cip->tlb_shootdown = 1;
+ lapic_send_ipi(cip->apicid, IPI_SHORTHAND_NONE, TLB_VECTOR);
+ spinlock_release(&cip->lock);
+ }
+}
+
+void
md_backtrace(void)
{
uintptr_t *rbp;
@@ -166,7 +212,7 @@ cpu_halt_all(void)
}
/* Send IPI to all cores */
- lapic_send_ipi(0, IPI_SHORTHAND_ALL, halt_vector);
+ lapic_send_ipi(0, IPI_SHORTHAND_ALL, HALT_VECTOR);
for (;;);
}
diff --git a/sys/arch/amd64/amd64/mp.c b/sys/arch/amd64/amd64/mp.c
index 22561d7..1e6d8d9 100644
--- a/sys/arch/amd64/amd64/mp.c
+++ b/sys/arch/amd64/amd64/mp.c
@@ -29,6 +29,7 @@
#include <sys/types.h>
#include <sys/limine.h>
+#include <sys/limits.h>
#include <sys/syslog.h>
#include <sys/spinlock.h>
#include <sys/sched.h>
@@ -45,7 +46,9 @@ static volatile struct limine_smp_request g_smp_req = {
.revision = 0
};
-static volatile uint32_t ncpu_up = 0;
+static volatile uint32_t ncpu_up = 1;
+static struct cpu_info *ci_list[CPU_MAX];
+static struct spinlock ci_list_lock = {0};
static void
ap_trampoline(struct limine_smp_info *si)
@@ -57,11 +60,31 @@ ap_trampoline(struct limine_smp_info *si)
memset(ci, 0, sizeof(*ci));
cpu_startup(ci);
+ spinlock_acquire(&ci_list_lock);
+ ci_list[ncpu_up] = ci;
+ spinlock_release(&ci_list_lock);
+
atomic_inc_int(&ncpu_up);
sched_enter();
while (1);
}
+struct cpu_info *
+cpu_get(uint32_t index)
+{
+ if (index >= ncpu_up) {
+ return NULL;
+ }
+
+ return ci_list[index];
+}
+
+uint32_t
+cpu_count(void)
+{
+ return ncpu_up;
+}
+
void
mp_bootstrap_aps(struct cpu_info *ci)
{
@@ -74,6 +97,7 @@ mp_bootstrap_aps(struct cpu_info *ci)
cpus = resp->cpus;
cpu_init_counter = resp->cpu_count - 1;
+ ci_list[0] = ci;
if (resp->cpu_count == 1) {
pr_trace("CPU has 1 core, no APs to bootstrap...\n");
@@ -91,5 +115,5 @@ mp_bootstrap_aps(struct cpu_info *ci)
}
/* Wait for all cores to be ready */
- while (ncpu_up < cpu_init_counter);
+ while ((ncpu_up - 1) < cpu_init_counter);
}
diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c
index 2e62a4b..0bdf3b7 100644
--- a/sys/arch/amd64/amd64/pmap.c
+++ b/sys/arch/amd64/amd64/pmap.c
@@ -33,6 +33,8 @@
#include <sys/errno.h>
#include <machine/tlb.h>
#include <machine/vas.h>
+#include <machine/cpu.h>
+#include <machine/cdefs.h>
#include <vm/pmap.h>
#include <vm/physmem.h>
#include <vm/vm.h>
@@ -303,3 +305,37 @@ pmap_set_cache(struct vas vas, vaddr_t va, int type)
return 0;
}
+
+bool
+pmap_is_clean(struct vas vas, vaddr_t va)
+{
+ uintptr_t *tbl;
+ int status;
+ size_t idx;
+
+ if ((status = pmap_get_tbl(vas, va, false, &tbl)) != 0)
+ return status;
+
+ idx = pmap_get_level_index(1, va);
+ return ISSET(tbl[idx], PTE_DIRTY) == 0;
+}
+
+void
+pmap_mark_clean(struct vas vas, vaddr_t va)
+{
+ uintptr_t *tbl;
+ int status;
+ size_t idx;
+
+ if ((status = pmap_get_tbl(vas, va, false, &tbl)) != 0)
+ return;
+
+ idx = pmap_get_level_index(1, va);
+ tbl[idx] &= ~PTE_DIRTY;
+
+ if (cpu_count() > 1) {
+ cpu_shootdown_tlb(va);
+ } else {
+ __invlpg(va);
+ }
+}
diff --git a/sys/arch/amd64/amd64/proc_machdep.c b/sys/arch/amd64/amd64/proc_machdep.c
index f6b91f9..4fe8580 100644
--- a/sys/arch/amd64/amd64/proc_machdep.c
+++ b/sys/arch/amd64/amd64/proc_machdep.c
@@ -123,24 +123,37 @@ md_td_kick(struct proc *td)
{
struct trapframe *tfp;
struct cpu_info *ci;
+ uint8_t rpl;
+ uint16_t ds = KERNEL_DS;
tfp = &td->tf;
+ rpl = tfp->cs & 3;
ci = this_cpu();
ci->curtd = td;
+ if (rpl == 3) {
+ td->flags &= ~PROC_KTD;
+ ds = USER_DS | 3;
+ }
+
__ASMV(
- "push %0\n"
+ "mov %0, %%rax\n"
"push %1\n"
- "pushf\n"
"push %2\n"
"push %3\n"
+ "push %%rax\n"
+ "push %4\n"
+ "test $3, %%ax\n"
+ "jz 1f\n"
"lfence\n"
"swapgs\n"
- "iretq"
+ "1:\n"
+ " iretq"
:
- : "i" (USER_DS | 3),
+ : "r" (tfp->cs),
+ "r" (ds),
"r" (tfp->rsp),
- "i" (USER_CS | 3),
+ "m" (tfp->rflags),
"r" (tfp->rip)
);
diff --git a/sys/arch/amd64/amd64/vector.S b/sys/arch/amd64/amd64/vector.S
index 32ccd34..d2a3d89 100644
--- a/sys/arch/amd64/amd64/vector.S
+++ b/sys/arch/amd64/amd64/vector.S
@@ -64,69 +64,69 @@ done:
.globl pin_isr_load
pin_isr_load:
- IDT_SET_VEC 34, ioapic_edge_0
- IDT_SET_VEC 35, ioapic_edge_1
- IDT_SET_VEC 36, ioapic_edge_2
- IDT_SET_VEC 37, ioapic_edge_3
- IDT_SET_VEC 38, ioapic_edge_4
- IDT_SET_VEC 39, ioapic_edge_5
- IDT_SET_VEC 40, ioapic_edge_6
- IDT_SET_VEC 41, ioapic_edge_7
- IDT_SET_VEC 42, ioapic_edge_8
- IDT_SET_VEC 43, ioapic_edge_9
- IDT_SET_VEC 44, ioapic_edge_10
- IDT_SET_VEC 45, ioapic_edge_11
- IDT_SET_VEC 46, ioapic_edge_12
- IDT_SET_VEC 47, ioapic_edge_13
- IDT_SET_VEC 48, ioapic_edge_14
- IDT_SET_VEC 49, ioapic_edge_15
- IDT_SET_VEC 50, ioapic_edge_16
- IDT_SET_VEC 51, ioapic_edge_17
- IDT_SET_VEC 52, ioapic_edge_18
- IDT_SET_VEC 53, ioapic_edge_19
- IDT_SET_VEC 54, ioapic_edge_20
- IDT_SET_VEC 55, ioapic_edge_21
- IDT_SET_VEC 56, ioapic_edge_22
- IDT_SET_VEC 57, ioapic_edge_23
- IDT_SET_VEC 58, ioapic_edge_24
- IDT_SET_VEC 59, ioapic_edge_25
- IDT_SET_VEC 60, ioapic_edge_26
- IDT_SET_VEC 61, ioapic_edge_27
- IDT_SET_VEC 62, ioapic_edge_28
- IDT_SET_VEC 63, ioapic_edge_29
- IDT_SET_VEC 64, ioapic_edge_30
- IDT_SET_VEC 65, ioapic_edge_31
- IDT_SET_VEC 66, ioapic_edge_32
- IDT_SET_VEC 67, ioapic_edge_33
- IDT_SET_VEC 68, ioapic_edge_34
- IDT_SET_VEC 69, ioapic_edge_35
- IDT_SET_VEC 70, ioapic_edge_36
- IDT_SET_VEC 71, ioapic_edge_37
- IDT_SET_VEC 72, ioapic_edge_38
- IDT_SET_VEC 73, ioapic_edge_39
- IDT_SET_VEC 74, ioapic_edge_40
- IDT_SET_VEC 75, ioapic_edge_41
- IDT_SET_VEC 76, ioapic_edge_42
- IDT_SET_VEC 77, ioapic_edge_43
- IDT_SET_VEC 78, ioapic_edge_44
- IDT_SET_VEC 79, ioapic_edge_45
- IDT_SET_VEC 80, ioapic_edge_46
- IDT_SET_VEC 81, ioapic_edge_47
- IDT_SET_VEC 82, ioapic_edge_48
- IDT_SET_VEC 83, ioapic_edge_49
- IDT_SET_VEC 84, ioapic_edge_50
- IDT_SET_VEC 85, ioapic_edge_51
- IDT_SET_VEC 86, ioapic_edge_52
- IDT_SET_VEC 87, ioapic_edge_53
- IDT_SET_VEC 88, ioapic_edge_54
- IDT_SET_VEC 89, ioapic_edge_55
- IDT_SET_VEC 90, ioapic_edge_56
- IDT_SET_VEC 91, ioapic_edge_57
- IDT_SET_VEC 92, ioapic_edge_58
- IDT_SET_VEC 93, ioapic_edge_59
- IDT_SET_VEC 94, ioapic_edge_60
- IDT_SET_VEC 95, ioapic_edge_61
- IDT_SET_VEC 96, ioapic_edge_62
+ IDT_SET_VEC 35, ioapic_edge_0
+ IDT_SET_VEC 36, ioapic_edge_1
+ IDT_SET_VEC 37, ioapic_edge_2
+ IDT_SET_VEC 38, ioapic_edge_3
+ IDT_SET_VEC 39, ioapic_edge_4
+ IDT_SET_VEC 40, ioapic_edge_5
+ IDT_SET_VEC 41, ioapic_edge_6
+ IDT_SET_VEC 42, ioapic_edge_7
+ IDT_SET_VEC 43, ioapic_edge_8
+ IDT_SET_VEC 44, ioapic_edge_9
+ IDT_SET_VEC 45, ioapic_edge_10
+ IDT_SET_VEC 46, ioapic_edge_11
+ IDT_SET_VEC 47, ioapic_edge_12
+ IDT_SET_VEC 48, ioapic_edge_13
+ IDT_SET_VEC 49, ioapic_edge_14
+ IDT_SET_VEC 50, ioapic_edge_15
+ IDT_SET_VEC 51, ioapic_edge_16
+ IDT_SET_VEC 52, ioapic_edge_17
+ IDT_SET_VEC 53, ioapic_edge_18
+ IDT_SET_VEC 54, ioapic_edge_19
+ IDT_SET_VEC 55, ioapic_edge_20
+ IDT_SET_VEC 56, ioapic_edge_21
+ IDT_SET_VEC 57, ioapic_edge_22
+ IDT_SET_VEC 58, ioapic_edge_23
+ IDT_SET_VEC 59, ioapic_edge_24
+ IDT_SET_VEC 60, ioapic_edge_25
+ IDT_SET_VEC 61, ioapic_edge_26
+ IDT_SET_VEC 62, ioapic_edge_27
+ IDT_SET_VEC 63, ioapic_edge_28
+ IDT_SET_VEC 64, ioapic_edge_29
+ IDT_SET_VEC 65, ioapic_edge_30
+ IDT_SET_VEC 66, ioapic_edge_31
+ IDT_SET_VEC 67, ioapic_edge_32
+ IDT_SET_VEC 68, ioapic_edge_33
+ IDT_SET_VEC 69, ioapic_edge_34
+ IDT_SET_VEC 70, ioapic_edge_35
+ IDT_SET_VEC 71, ioapic_edge_36
+ IDT_SET_VEC 72, ioapic_edge_37
+ IDT_SET_VEC 73, ioapic_edge_38
+ IDT_SET_VEC 74, ioapic_edge_39
+ IDT_SET_VEC 75, ioapic_edge_40
+ IDT_SET_VEC 76, ioapic_edge_41
+ IDT_SET_VEC 77, ioapic_edge_42
+ IDT_SET_VEC 78, ioapic_edge_43
+ IDT_SET_VEC 79, ioapic_edge_44
+ IDT_SET_VEC 80, ioapic_edge_45
+ IDT_SET_VEC 81, ioapic_edge_46
+ IDT_SET_VEC 82, ioapic_edge_47
+ IDT_SET_VEC 83, ioapic_edge_48
+ IDT_SET_VEC 84, ioapic_edge_49
+ IDT_SET_VEC 85, ioapic_edge_50
+ IDT_SET_VEC 86, ioapic_edge_51
+ IDT_SET_VEC 87, ioapic_edge_52
+ IDT_SET_VEC 88, ioapic_edge_53
+ IDT_SET_VEC 89, ioapic_edge_54
+ IDT_SET_VEC 90, ioapic_edge_55
+ IDT_SET_VEC 91, ioapic_edge_56
+ IDT_SET_VEC 92, ioapic_edge_57
+ IDT_SET_VEC 93, ioapic_edge_58
+ IDT_SET_VEC 94, ioapic_edge_59
+ IDT_SET_VEC 95, ioapic_edge_60
+ IDT_SET_VEC 96, ioapic_edge_61
+ IDT_SET_VEC 97, ioapic_edge_62
IDT_SET_VEC 97, ioapic_edge_63
ret
diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index 9ab109a..5276eea 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -37,6 +37,7 @@
#include <dev/usb/xhciregs.h>
#include <dev/usb/xhcivar.h>
#include <dev/pci/pci.h>
+#include <dev/pci/pciregs.h>
#include <dev/acpi/acpi.h>
#include <vm/physmem.h>
#include <vm/dynalloc.h>
@@ -496,6 +497,16 @@ xhci_init_hc(struct xhci_hc *hc)
return 0;
}
+static void
+xhci_init_pci(void)
+{
+ uint32_t tmp;
+
+ tmp = pci_readl(hci_dev, PCIREG_CMDSTATUS);
+ tmp |= (PCI_BUS_MASTERING | PCI_MEM_SPACE);
+ pci_writel(hci_dev, PCIREG_CMDSTATUS, tmp);
+}
+
static int
xhci_init(void)
{
@@ -528,6 +539,7 @@ xhci_init(void)
return -ENODEV;
}
+ xhci_init_pci();
return xhci_init_hc(&xhc);
}
diff --git a/sys/include/arch/amd64/cdefs.h b/sys/include/arch/amd64/cdefs.h
index bab0c89..0a20324 100644
--- a/sys/include/arch/amd64/cdefs.h
+++ b/sys/include/arch/amd64/cdefs.h
@@ -43,4 +43,13 @@
#define md_inton() __ASMV("sti") /* Enable interrupts */
#define md_hlt() __ASMV("hlt") /* Halt the processor */
+/*
+ * AMD64 specific defines
+ */
+#define __invlpg(VA) \
+ __ASMV("invlpg %0" \
+ : \
+ : "m" ((VA)) \
+ : "memory")
+
#endif /* !_AMD64_CDEFS_H_ */
diff --git a/sys/include/arch/amd64/cpu.h b/sys/include/arch/amd64/cpu.h
index dd753b7..2d08d6e 100644
--- a/sys/include/arch/amd64/cpu.h
+++ b/sys/include/arch/amd64/cpu.h
@@ -33,6 +33,7 @@
#include <sys/types.h>
#include <sys/cdefs.h>
#include <sys/proc.h>
+#include <sys/spinlock.h>
#include <machine/tss.h>
#define CPU_IRQ(IRQ_N) (BIT((IRQ_N)) & 0xFF)
@@ -40,11 +41,14 @@
struct cpu_info {
uint32_t apicid;
uint8_t has_x2apic : 1;
+ uint8_t tlb_shootdown : 1;
uint8_t ipl;
size_t lapic_tmr_freq;
uint8_t irq_mask;
+ vaddr_t shootdown_va;
struct tss_entry *tss;
struct proc *curtd;
+ struct spinlock lock;
struct cpu_info *self;
};
@@ -52,6 +56,10 @@ __dead void cpu_halt_all(void);
void cpu_halt_others(void);
void cpu_startup(struct cpu_info *ci);
+struct cpu_info *cpu_get(uint32_t index);
+uint32_t cpu_count(void);
+void cpu_shootdown_tlb(vaddr_t va);
+
struct cpu_info *this_cpu(void);
void mp_bootstrap_aps(struct cpu_info *ci);
diff --git a/sys/include/sys/driver.h b/sys/include/sys/driver.h
index 6e4a267..8ab9521 100644
--- a/sys/include/sys/driver.h
+++ b/sys/include/sys/driver.h
@@ -110,7 +110,7 @@ extern char __driversd_init_end[];
}
#define DRIVERS_SCHED() \
- spawn(&g_proc0,__driver_init_td, NULL, 0, NULL)
+ spawn(&g_proc0, __driver_init_td, NULL, 0, NULL)
void __driver_init_td(void);
diff --git a/sys/include/sys/limits.h b/sys/include/sys/limits.h
index 6185719..198c963 100644
--- a/sys/include/sys/limits.h
+++ b/sys/include/sys/limits.h
@@ -33,5 +33,7 @@
#define PATH_MAX 1024
#define SSIZE_MAX 32767
#define CHAR_BIT 8
-
+#if defined(_KERNEL)
+#define CPU_MAX 256
+#endif /* _KERNEL */
#endif /* !_SYS_LIMITS_H_ */
diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h
index 0a7d133..25f5fd3 100644
--- a/sys/include/sys/proc.h
+++ b/sys/include/sys/proc.h
@@ -64,7 +64,7 @@ struct proc {
struct trapframe tf;
struct pcb pcb;
struct proc *parent;
- void *spawn_data;
+ void *data;
size_t priority;
int exit_status;
bool rested;
@@ -84,9 +84,12 @@ struct proc {
#define PROC_LEAFQ BIT(3) /* Leaf queue is active */
#define PROC_WAITED BIT(4) /* Being waited on by parent */
#define PROC_KTD BIT(5) /* Kernel thread */
+#define PROC_SLEEP BIT(6) /* Thread execution paused */
struct proc *this_td(void);
struct proc *get_child(struct proc *cur, pid_t pid);
+void proc_reap(struct proc *td);
+
int md_spawn(struct proc *p, struct proc *parent, uintptr_t ip);
scret_t sys_spawn(struct syscall_args *scargs);
diff --git a/sys/include/sys/sched.h b/sys/include/sys/sched.h
index 80f4d1c..7d17607 100644
--- a/sys/include/sys/sched.h
+++ b/sys/include/sys/sched.h
@@ -37,6 +37,8 @@
void sched_init(void);
void sched_yield(void);
+
+void sched_switch_to(struct trapframe *tf, struct proc *td);
void sched_detach(struct proc *td);
__dead void sched_enter(void);
diff --git a/sys/include/sys/spawn.h b/sys/include/sys/spawn.h
index 3828d5c..9d823db 100644
--- a/sys/include/sys/spawn.h
+++ b/sys/include/sys/spawn.h
@@ -31,6 +31,9 @@
#define _SYS_SPAWN_H_
#include <sys/types.h>
+#include <sys/param.h>
+
+#define SPAWN_WAIT BIT(0)
#if !defined(_KERNEL)
pid_t spawn(const char *pathname, int flags);
diff --git a/sys/include/vm/pmap.h b/sys/include/vm/pmap.h
index 9eed184..e1f3f89 100644
--- a/sys/include/vm/pmap.h
+++ b/sys/include/vm/pmap.h
@@ -76,6 +76,17 @@ int pmap_map(struct vas vas, vaddr_t va, paddr_t pa, vm_prot_t prot);
int pmap_unmap(struct vas vas, vaddr_t va);
/*
+ * Returns true if the page is clean (modified), otherwise
+ * returns false.
+ */
+bool pmap_is_clean(struct vas vas, vaddr_t va);
+
+/*
+ * Marks a page as clean (unmodified)
+ */
+void pmap_mark_clean(struct vas vas, vaddr_t va);
+
+/*
* Mark a virtual address with a specific
* caching type.
*/
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index dd14267..1992d46 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -187,6 +187,7 @@ fd_rw(unsigned int fd, void *buf, size_t count, uint8_t write)
sio.buf = kbuf;
sio.offset = filedes->offset;
+ spinlock_acquire(&filedes->lock);
if (write) {
/* Copy in user buffer */
if (copyin(buf, kbuf, count) < 0) {
@@ -224,6 +225,7 @@ done:
if (kbuf != NULL) {
dynfree(kbuf);
}
+ spinlock_release(&filedes->lock);
return retval;
}
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index bf6a26e..b760912 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -37,6 +37,7 @@
#include <vm/map.h>
#include <vm/physmem.h>
#include <machine/pcb.h>
+#include <machine/cdefs.h>
#include <string.h>
/*
@@ -87,6 +88,7 @@ execve(struct proc *td, const struct execve_args *args)
release_stack(td);
/* Save program state */
+ md_intoff();
memcpy(&td->exec, &prog, sizeof(td->exec));
/* Set new stack and map it to userspace */
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 242b221..b6cbc4e 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -78,6 +78,30 @@ unload_td(struct proc *td)
}
}
+void
+proc_reap(struct proc *td)
+{
+ struct pcb *pcbp;
+ uintptr_t stack;
+
+ pcbp = &td->pcb;
+ stack = td->stack_base;
+
+ /*
+ * If this is on the higher half, it is kernel
+ * mapped and we need to convert it to a physical
+ * address.
+ */
+ if (stack >= VM_HIGHER_HALF) {
+ stack -= VM_HIGHER_HALF;
+ }
+
+ unload_td(td);
+ vm_unmap(pcbp->addrsp, td->stack_base, PROC_STACK_SIZE);
+ vm_free_frame(stack, PROC_STACK_PAGES);
+ pmap_destroy_vas(pcbp->addrsp);
+}
+
/*
* Kill a thread and deallocate its resources.
*
@@ -86,20 +110,18 @@ unload_td(struct proc *td)
int
exit1(struct proc *td, int flags)
{
- struct pcb *pcbp;
struct proc *curtd, *procp;
+ struct proc *parent;
struct cpu_info *ci;
- uintptr_t stack;
pid_t target_pid, curpid;
ci = this_cpu();
target_pid = td->pid;
curtd = this_td();
- pcbp = &td->pcb;
curpid = curtd->pid;
- stack = td->stack_base;
td->flags |= PROC_EXITING;
+ parent = td->parent;
/* If we have any children, kill them too */
if (td->nleaves > 0) {
@@ -108,20 +130,10 @@ exit1(struct proc *td, int flags)
}
}
- /*
- * If this is on the higher half, it is kernel
- * mapped and we need to convert it to a physical
- * address.
- */
- if (stack >= VM_HIGHER_HALF) {
- stack -= VM_HIGHER_HALF;
+ if (target_pid != curpid) {
+ proc_reap(td);
}
- unload_td(td);
- vm_unmap(pcbp->addrsp, td->stack_base, PROC_STACK_SIZE);
- vm_free_frame(stack, PROC_STACK_PAGES);
- pmap_destroy_vas(pcbp->addrsp);
-
/*
* Only free the process structure if we aren't
* being waited on, otherwise let it be so the
@@ -139,6 +151,13 @@ exit1(struct proc *td, int flags)
*/
if (target_pid == curpid) {
ci->curtd = NULL;
+ if (parent->pid == 0)
+ sched_enter();
+ if (td->data == NULL)
+ sched_enter();
+
+ sched_enqueue_td(parent);
+ parent->flags &= ~PROC_SLEEP;
sched_enter();
}
@@ -153,6 +172,7 @@ 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_sched.c b/sys/kern/kern_sched.c
index 2fe0f32..8e456d2 100644
--- a/sys/kern/kern_sched.c
+++ b/sys/kern/kern_sched.c
@@ -104,12 +104,22 @@ sched_dequeue_td(void)
for (size_t i = 0; i < SCHED_NQUEUE; ++i) {
queue = &qlist[i];
- if (!TAILQ_EMPTY(&queue->q)) {
- td = TAILQ_FIRST(&queue->q);
- TAILQ_REMOVE(&queue->q, td, link);
- spinlock_release(&tdq_lock);
- return td;
+ if (TAILQ_EMPTY(&queue->q)) {
+ continue;
}
+
+ td = TAILQ_FIRST(&queue->q);
+ if (td == NULL) {
+ continue;
+ }
+
+ TAILQ_REMOVE(&queue->q, td, link);
+ if (ISSET(td->flags, PROC_SLEEP)) {
+ continue;
+ }
+
+ spinlock_release(&tdq_lock);
+ return td;
}
/* We got nothing */
@@ -125,6 +135,10 @@ sched_enqueue_td(struct proc *td)
{
struct sched_queue *queue;
+ if (ISSET(td->flags, PROC_SLEEP)) {
+ return;
+ }
+
spinlock_acquire(&tdq_lock);
queue = &qlist[td->priority];
@@ -176,15 +190,31 @@ td_pri_update(struct proc *td)
}
}
+void
+sched_switch_to(struct trapframe *tf, struct proc *td)
+{
+ struct cpu_info *ci;
+ struct pcb *pcbp;
+
+ ci = this_cpu();
+
+ if (tf != NULL) {
+ memcpy(tf, &td->tf, sizeof(*tf));
+ }
+
+ ci->curtd = td;
+ pcbp = &td->pcb;
+ pmap_switch_vas(pcbp->addrsp);
+}
+
/*
* Perform a context switch.
*/
void
sched_switch(struct trapframe *tf)
{
- struct cpu_info *ci;
- struct pcb *pcbp;
struct proc *next_td, *td;
+ struct cpu_info *ci;
ci = this_cpu();
td = ci->curtd;
@@ -203,11 +233,7 @@ sched_switch(struct trapframe *tf)
return;
}
- memcpy(tf, &next_td->tf, sizeof(*tf));
- ci->curtd = next_td;
- pcbp = &next_td->pcb;
-
- pmap_switch_vas(pcbp->addrsp);
+ sched_switch_to(tf, next_td);
sched_oneshot(false);
}
@@ -217,6 +243,7 @@ sched_switch(struct trapframe *tf)
void
sched_enter(void)
{
+ md_inton();
sched_oneshot(false);
for (;;) {
md_pause();
@@ -226,12 +253,20 @@ sched_enter(void)
void
sched_yield(void)
{
- struct proc *td = this_td();
+ struct proc *td;
+ struct cpu_info *ci = this_cpu();
- if (td != NULL) {
- td->rested = true;
- sched_switch(&td->tf);
+ if ((td = ci->curtd) == NULL) {
+ return;
}
+
+ td->rested = true;
+ ci->curtd = NULL;
+
+ md_inton();
+ sched_oneshot(false);
+ md_hlt();
+ ci->curtd = td;
}
void
diff --git a/sys/kern/kern_spawn.c b/sys/kern/kern_spawn.c
index 032ba24..4105668 100644
--- a/sys/kern/kern_spawn.c
+++ b/sys/kern/kern_spawn.c
@@ -27,6 +27,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/spawn.h>
#include <sys/proc.h>
#include <sys/exec.h>
#include <sys/mman.h>
@@ -70,7 +71,7 @@ spawn_thunk(void)
char *envp[] = { NULL };
cur = this_td();
- args = cur->spawn_data;
+ args = cur->data;
path = args->path;
memcpy(pathbuf, path, strlen(path));
@@ -110,6 +111,7 @@ spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **new
struct proc *newproc;
struct mmap_lgdr *mlgdr;
int error;
+ pid_t pid;
newproc = dynalloc(sizeof(*newproc));
if (newproc == NULL) {
@@ -150,7 +152,7 @@ spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **new
TAILQ_INSERT_TAIL(&cur->leafq, newproc, leaf_link);
atomic_inc_int(&cur->nleaves);
newproc->parent = cur;
- newproc->spawn_data = p;
+ newproc->data = p;
/* Initialize the mmap ledger */
mlgdr->nbytes = 0;
@@ -160,7 +162,25 @@ spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **new
newproc->pid = ++nthreads;
signals_init(newproc);
sched_enqueue_td(newproc);
- return newproc->pid;
+ pid = newproc->pid;
+
+ if (ISSET(flags, SPAWN_WAIT)) {
+ newproc->flags |= PROC_WAITED;
+ cur->flags |= PROC_SLEEP;
+
+ while (ISSET(cur->flags, PROC_SLEEP)) {
+ sched_yield();
+ }
+
+ if (!ISSET(newproc->flags, PROC_ZOMB)) {
+ pr_error("spawn: fatal: %d not zombie\n", newproc->pid);
+ panic("possibly memory corruption\n");
+ }
+
+ proc_reap(newproc);
+ }
+
+ return pid;
}
/*