diff options
Diffstat (limited to 'sys')
28 files changed, 1031 insertions, 78 deletions
diff --git a/sys/arch/amd64/amd64/intr.c b/sys/arch/amd64/amd64/intr.c index 685a16d..a545788 100644 --- a/sys/arch/amd64/amd64/intr.c +++ b/sys/arch/amd64/amd64/intr.c @@ -129,6 +129,7 @@ intr_register(const char *name, const struct intr_hand *ih) ih_new->priority = ih->priority; ih_new->irq = ih->irq; ih_new->vector = i; + ih_new->nintr = 0; g_intrs[i] = ih_new; if (ih->irq >= 0) { diff --git a/sys/arch/amd64/amd64/lapic_intr.S b/sys/arch/amd64/amd64/lapic_intr.S index 5ae8f39..1413660 100644 --- a/sys/arch/amd64/amd64/lapic_intr.S +++ b/sys/arch/amd64/amd64/lapic_intr.S @@ -33,6 +33,6 @@ .globl lapic_tmr_isr INTRENTRY(lapic_tmr_isr, handle_lapic_tmr) handle_lapic_tmr: - call sched_switch // Context switch per every timer IRQ + call md_sched_switch // Context switch per every timer IRQ call lapic_eoi // Done! Signal that we finished to the Local APIC retq diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index d310460..40950f9 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -187,9 +187,10 @@ enable_simd(void) } static void -cpu_check_feat(struct cpu_info *ci) +cpu_get_info(struct cpu_info *ci) { - uint32_t unused, ebx; + uint32_t eax, ebx, unused; + uint8_t ext_model, ext_family; /* Extended features */ CPUID(0x07, unused, ebx, unused, unused); @@ -197,6 +198,33 @@ cpu_check_feat(struct cpu_info *ci) ci->feat |= CPU_FEAT_SMEP; if (ISSET(ebx, BIT(20))) ci->feat |= CPU_FEAT_SMAP; + + /* + * Processor info and feature bits + */ + CPUID(0x01, eax, unused, unused, unused); + ci->model = (eax >> 4) & 0xF; + ci->family = (eax >> 8) & 0xF; + + /* + * If the family ID is 15 then the actual family + * ID is the sum of the extended family and the + * family ID fields. + */ + if (ci->family == 0xF) { + ext_family = (eax >> 20) & 0xFF; + ci->family += ext_family; + } + + /* + * If the family has the value of either 6 or 15, + * then the extended model number would be used. + * Slap them together if this is the case. + */ + if (ci->family == 6 || ci->family == 15) { + ext_model = (eax >> 16) & 0xF; + ci->model |= (ext_model << 4); + } } void @@ -383,7 +411,7 @@ cpu_startup(struct cpu_info *ci) init_tss(ci); try_mitigate_spectre(); - cpu_check_feat(ci); + cpu_get_info(ci); cpu_enable_smep(); enable_simd(); diff --git a/sys/arch/amd64/amd64/mp.c b/sys/arch/amd64/amd64/mp.c index dbee32c..21881b2 100644 --- a/sys/arch/amd64/amd64/mp.c +++ b/sys/arch/amd64/amd64/mp.c @@ -81,6 +81,24 @@ cpu_get(uint32_t index) return ci_list[index]; } +/* + * Grab the CPU stat structured of a specified + * processor + * + * @cpu_index: CPU index number + */ +struct sched_cpu * +cpu_get_stat(uint32_t cpu_index) +{ + struct cpu_info *ci; + + if ((ci = cpu_get(cpu_index)) == NULL) { + return NULL; + } + + return &ci->stat; +} + uint32_t cpu_count(void) { diff --git a/sys/arch/amd64/amd64/proc_machdep.c b/sys/arch/amd64/amd64/proc_machdep.c index 63604a4..ad807fe 100644 --- a/sys/arch/amd64/amd64/proc_machdep.c +++ b/sys/arch/amd64/amd64/proc_machdep.c @@ -32,6 +32,8 @@ #include <sys/param.h> #include <sys/errno.h> #include <sys/exec.h> +#include <sys/sched.h> +#include <sys/schedvar.h> #include <machine/frame.h> #include <machine/gdt.h> #include <machine/cpu.h> @@ -220,3 +222,72 @@ md_spawn(struct proc *p, struct proc *parent, uintptr_t ip) tfp->rsp = ALIGN_DOWN((stack_base + PROC_STACK_SIZE) - 1, 16); return 0; } + +/* + * Save thread state and enqueue it back into one + * of the ready queues. + */ +static void +sched_save_td(struct proc *td, struct trapframe *tf) +{ + /* + * Save trapframe to process structure only + * if PROC_EXEC is not set. + */ + if (!ISSET(td->flags, PROC_EXEC)) { + memcpy(&td->tf, tf, sizeof(td->tf)); + } + + sched_enqueue_td(td); +} + +static void +sched_switch_to(struct trapframe *tf, struct proc *td) +{ + struct cpu_info *ci; + struct sched_cpu *cpustat; + struct pcb *pcbp; + + ci = this_cpu(); + + if (tf != NULL) { + memcpy(tf, &td->tf, sizeof(*tf)); + } + + /* Update stats */ + cpustat = &ci->stat; + cpustat->nswitch++; + + ci->curtd = td; + pcbp = &td->pcb; + pmap_switch_vas(pcbp->addrsp); +} + +/* + * Perform a context switch. + */ +void +md_sched_switch(struct trapframe *tf) +{ + struct proc *next_td, *td; + struct cpu_info *ci; + + ci = this_cpu(); + td = ci->curtd; + mi_sched_switch(td); + + if (td != NULL) { + if (td->pid == 0) + return; + + sched_save_td(td, tf); + } + + if ((next_td = sched_dequeue_td()) == NULL) { + sched_oneshot(false); + return; + } + + sched_switch_to(tf, next_td); + sched_oneshot(false); +} diff --git a/sys/arch/amd64/amd64/vector.S b/sys/arch/amd64/amd64/vector.S index c820a41..890b314 100644 --- a/sys/arch/amd64/amd64/vector.S +++ b/sys/arch/amd64/amd64/vector.S @@ -51,16 +51,22 @@ ioapic_common_func: jz 1f // Nope, return mov (%rdx), %rbx // intr_hand.func - add $8, %rdx // Get interrupt data + add $16, %rdx // Get interrupt data mov %rdx, %rdi // Pass the interrupt data push %rcx // Save our counter + push %rdx call *%rbx // Call the handler + pop %rdx pop %rcx // Restore our counter or %rax, %rax // Was it theirs? (RET >= 1) - jnz done // Yes, we are done. + jnz handled // Yes, we are done. 1: inc %rcx // Next cmp $256, %rcx // Did we reach the end? jl .walk // Nope, keep going + jmp done // Out of entries +handled: + sub $8, %rdx + addq $1, (%rdx) done: call lapic_eoi retq diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC index 95fe2e0..e407fa9 100644 --- a/sys/arch/amd64/conf/GENERIC +++ b/sys/arch/amd64/conf/GENERIC @@ -10,6 +10,7 @@ option SERIAL_DEBUG yes // Enable kmsg serial logging option USER_KMSG no // Show kmsg in user consoles option CPU_SMEP yes // Supervisor Memory Exec Protection option PANIC_SCR no // Clear screen on panic +option I8042_POLL yes // Use polling for the i8042 // Kernel constants setval SCHED_NQUEUE 4 // Number of scheduler queues (for MLFQ) diff --git a/sys/arch/amd64/isa/i8042.c b/sys/arch/amd64/isa/i8042.c index cde70ff..3ae645d 100644 --- a/sys/arch/amd64/isa/i8042.c +++ b/sys/arch/amd64/isa/i8042.c @@ -53,6 +53,13 @@ #include <string.h> #include <assert.h> +/* From kconf(9) */ +#if !defined(__I8042_POLL) +#define I8042_POLL 0 +#else +#define I8042_POLL __I8042_POLL +#endif + #define KEY_REP_MAX 2 #define pr_trace(fmt, ...) kprintf("i8042: " fmt, ##__VA_ARGS__) @@ -424,13 +431,20 @@ i8042_init(void) quirks |= I8042_HOSTILE; pr_trace("ThinkPad T420s detected, assuming hostile\n"); pr_trace("disabling irq 1, polling as fallback\n"); - spawn(&polltd, i8042_sync_loop, NULL, 0, NULL); } - if (!ISSET(quirks, I8042_HOSTILE)) { + /* + * If the i8042 has the hostile quirk or we are + * configured to poll for events, spawn the polling + * thread. + */ + if (!ISSET(quirks, I8042_HOSTILE) && !I8042_POLL) { /* Enable interrupts */ i8042_drain(); i8042_en_intr(); + } else if (ISSET(quirks, I8042_HOSTILE) || I8042_POLL) { + spawn(&polltd, i8042_sync_loop, NULL, 0, NULL); + pr_trace("polling events\n"); } i8042_write(I8042_CMD, I8042_ENABLE_PORT0); diff --git a/sys/dev/random/chacha20.c b/sys/crypto/chacha20.c index 41f823c..5c979a2 100644 --- a/sys/dev/random/chacha20.c +++ b/sys/crypto/chacha20.c @@ -27,7 +27,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include <dev/random/chacha20.h> +#include <crypto/chacha20.h> static const char sigma[16] = "expand 32-byte k"; diff --git a/sys/dev/random/siphash.c b/sys/crypto/siphash.c index 2b2243f..e0cad44 100644 --- a/sys/dev/random/siphash.c +++ b/sys/crypto/siphash.c @@ -29,7 +29,7 @@ Jean-Philippe Aumasson (https://131002.net/siphash/siphash24.c) */ -#include <dev/random/siphash.h> +#include <crypto/siphash.h> #include <stdint.h> #if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ diff --git a/sys/dev/phy/et131x.c b/sys/dev/phy/et131x.c new file mode 100644 index 0000000..d7764ae --- /dev/null +++ b/sys/dev/phy/et131x.c @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This driver is the product of reverse engineering + * work done by Ian Marco Moffett and the OSMORA team. + * + * Please refer to share/docs/hw/et131x.txt + */ + +#include <sys/types.h> +#include <sys/driver.h> +#include <sys/errno.h> +#include <sys/syslog.h> +#include <sys/mmio.h> +#include <dev/pci/pci.h> +#include <dev/pci/pciregs.h> +#include <dev/phy/et131xregs.h> +#include <dev/timer.h> +#include <net/if_var.h> + +#define VENDOR_ID 0x11C1 /* Agere */ +#define DEVICE_ID 0xED00 + +#define pr_trace(fmt, ...) kprintf("et131x: " fmt, ##__VA_ARGS__) +#define pr_error(...) pr_trace(__VA_ARGS__) + +/* + * The ET131X has 1024 words of internal RAM used to + * store/buffer packet data before reception or transmission. + * The card allows us to decide how large the TX/RX buffers would + * be split up. We split the RX/TX 50/50 as a nice balanced default. + * Might need to later adjust based on various system needs + * (e.g., heavy TX or RX) to avoid thrashing any of the buffers. + * + */ +#define INTERNAL_MEMSIZE 1024 /* In words */ +#define INTERNAL_MEM_RXOFF 0x1FF /* 50/50 split */ + +/* Helpful constants */ +#define ETHERFRAME_LEN 1518 /* Length of ethernet frame */ +#define ETHER_FCS_LEN 4 /* Length of frame check seq */ +#define RX_MEM_END 0x2BC + +struct netcard { + struct et131x_iospace *io; +}; + +static struct pci_device *dev; +static struct netcard g_card; +static struct timer tmr; + +/* + * Software reset the ET131X + * + * @io: Register space + */ +static void +et131x_soft_reset(struct netcard *card) +{ + struct et131x_iospace *io = card->io; + uint32_t tmp; + + tmp = ( + MAC_CFG1_RESET_TXMC | + MAC_CFG1_RESET_RXMC | + MAC_CFG1_RESET_TXFUNC | + MAC_CFG1_RESET_RXFUNC | + MAC_CFG1_SOFTRST | + MAC_CFG1_SIMRST + ); + + /* + * Reset the MAC core, bring it down. After that, + * we perform a global reset to bring the whole + * chip down. + */ + mmio_write32(&io->mac.cfg1, tmp); + mmio_write32(&io->global.sw_reset, GBL_RESET_ALL); + + /* + * Reset the MAC again for good measure, but + * this time a little softer. We already slammed + * the poor thing. + */ + tmp &= ~(MAC_CFG1_SOFTRST | MAC_CFG1_SIMRST); + mmio_write32(&io->mac.cfg1, tmp); + mmio_write32(&io->mac.cfg1, 0); +} + +/* + * Write to the PHY through MII + * + * @io: Register space + * @addr: PHY address + * @reg: PHY register + * @v: Value to write + */ +static int +et131x_mii_write(struct netcard *card, uint8_t addr, uint8_t reg, uint16_t v) +{ + struct et131x_iospace *io = card->io; + uint16_t mii_addr; + uint32_t tmp, mgmt_addr_old; + uint32_t mgmt_cmd_old; + uint8_t ndelay = 0; + int retval = 0; + + /* Save MII management regs state */ + mgmt_cmd_old = mmio_read32(&io->mac.mii_mgmt_cmd); + mgmt_addr_old = mmio_read32(&io->mac.mii_mgmt_addr); + mii_addr = MAC_MII_ADDR(addr, reg); + + /* + * Stop any transactions that are currently + * happening on the MDIO bus and prepare the + * write. + */ + mmio_write32(&io->mac.mii_mgmt_cmd, 0); + mmio_write32(&io->mac.mii_mgmt_addr, mii_addr); + mmio_write32(&io->mac.mii_mgmt_ctrl, v); + + for (;;) { + tmr.usleep(50); + ++ndelay; + + tmp = mmio_read32(&io->mac.mii_mgmt_indicator); + if (!ISSET(tmp, MAC_MGMT_BUSY)) + break; + if (ndelay >= 50) + break; + } + + if (ndelay >= 50) { + pr_error("could not write PHY reg %x (status=%x)\n", reg, tmp); + retval = -EIO; + goto done; + } + +done: + /* Stop operations and restore state */ + mmio_write32(&io->mac.mii_mgmt_cmd, 0); + mmio_write32(&io->mac.mii_mgmt_addr, mgmt_addr_old); + mmio_write32(&io->mac.mii_mgmt_cmd, mgmt_cmd_old); + return retval; +} + +/* + * Initialize PCI related things for the + * chip. + */ +static void +et131x_init_pci(void) +{ + uint32_t tmp; + + /* Enable bus mastering and MMIO */ + tmp = pci_readl(dev, PCIREG_CMDSTATUS); + tmp |= (PCI_BUS_MASTERING | PCI_MEM_SPACE); + pci_writel(dev, PCIREG_CMDSTATUS, tmp); +} + +/* + * Blink both LEDs of the card + * + * @io: Register space + * @count: Number of times to blink + * @delay: Millisecond delay between blinks + */ +static void +et131x_blink(struct netcard *card, uint32_t count, uint16_t delay) +{ + uint16_t on_val; + + on_val = (LED_ON << LED_LINK_SHIFT); + on_val |= (LED_ON << LED_TXRX_SHIFT); + for (uint32_t i = 0; i < count; ++i) { + et131x_mii_write(card, 0, PHY_LED2, on_val); + tmr.msleep(delay); + et131x_mii_write(card, 0, PHY_LED2, LED_ALL_OFF); + tmr.msleep(delay); + } +} + +/* + * Initialize the MAC into a functional + * state. + * + * @io: Register space. + */ +static void +et131x_mac_init(struct netcard *card) +{ + struct et131x_iospace *io = card->io; + struct mac_regs *mac = &io->mac; + struct global_regs *global = &io->global; + struct netif_addr addr; + uint32_t ipg_tmp, tmp; + + /* + * Okay so we need to reset the card so it doesn't + * do undefined bullshit. God forbid we get undefined + * behaviour without having a fucking official datasheet. + * Most would end themselves right then and there. + * + * Now, after we've done that, we must ensure that any + * packets larger than ETHERFRAME_LEN are truncated by + * the MAC. Again, something like an internal buffer + * overrun during TX/RX would be quite fucking horrible. + * + * We also want to clear the MAC interface control and MII + * clock to ensure it is in a known state. + */ + et131x_soft_reset(card); + mmio_write32(&mac->max_fm_len, ETHERFRAME_LEN); + mmio_write32(&mac->if_ctrl, 0); + mmio_write32(&mac->mii_mgmt_cfg, MAC_MIIMGMT_CLK_RST); + + /* + * Split the RX/TX memory 50/50, put the internal RX + * buffer right at the start into the first half, and + * the TX buffer right after the RX buffer. + */ + mmio_write32(&global->rxq_start, 0); + mmio_write32(&global->rxq_end, RX_MEM_END); + mmio_write32(&global->txq_start, RX_MEM_END + 1); + mmio_write32(&global->txq_end, INTERNAL_MEMSIZE - 1); + + /* Disable loopbacks, watchdog timer, clear MSI config */ + mmio_write32(&global->loopback, 0); + mmio_write32(&global->msi_config, 0); + mmio_write32(&global->watchdog_timer, 0); + + /* + * Set up half duplex config + * + * - BEB trunc (0xA) + * - Excess defer + * - Re-transmit (0xF) + * - Collision window + */ + mmio_write32(&mac->hfdp, 0x00A1F037); + + /* + * Setup the MAC interpacket gap register + * + * - IPG1 (0x38) + * - IPG2 (0x58) + * - B2B (0x60) + */ + ipg_tmp = ((0x50 << 8) | 0x38005860); + mmio_write32(&mac->ipg, ipg_tmp); + + /* MAC address dword 0 */ + tmp = pci_readl(dev, PCI_MAC_ADDRESS); + addr.data[0] = tmp & 0xFF; + addr.data[1] = (tmp >> 8) & 0xFF; + addr.data[2] = (tmp >> 16) & 0xFF; + addr.data[3] = (tmp >> 24) & 0xFF; + + /* MAC address word 1 */ + tmp = pci_readl(dev, PCI_MAC_ADDRESS + 4); + addr.data[4] = tmp & 0xFF; + addr.data[5] = (tmp >> 8) & 0xFF; + + /* Print out the MAC address */ + pr_trace("MAC address: %x:%x:%x:%x:%x:%x\n", + (uint64_t)addr.data[0], (uint64_t)addr.data[1], + (uint64_t)addr.data[2], (uint64_t)addr.data[3], + (uint64_t)addr.data[4], (uint64_t)addr.data[5]); +} + +static int +et131x_init(void) +{ + struct pci_lookup lookup; + int error; + + lookup.vendor_id = VENDOR_ID; + lookup.device_id = DEVICE_ID; + dev = pci_get_device(lookup, PCI_VENDOR_ID | PCI_DEVICE_ID); + if (dev == NULL) { + return -ENODEV; + } + + pr_trace("Agere ET1310 Ethernet ctl <phy? at pci%d:%x.%x.%d>\n", + dev->bus, dev->device_id, dev->func, + dev->slot); + + /* Try to request a general purpose timer */ + if (req_timer(TIMER_GP, &tmr) != TMRR_SUCCESS) { + pr_error("failed to fetch general purpose timer\n"); + return -ENODEV; + } + + /* Ensure it has get_time_usec() */ + if (tmr.usleep == NULL) { + pr_error("general purpose timer has no usleep()\n"); + return -ENODEV; + } + + if ((error = pci_map_bar(dev, 0, (void *)&g_card.io)) != 0) { + return error; + } + + et131x_init_pci(); + et131x_mac_init(&g_card); + et131x_blink(&g_card, 4, 150); + return 0; +} + +DRIVER_DEFER(et131x_init, "et131x"); diff --git a/sys/dev/random/entropy.c b/sys/dev/random/entropy.c index d392b9c..4e723a4 100644 --- a/sys/dev/random/entropy.c +++ b/sys/dev/random/entropy.c @@ -30,7 +30,7 @@ #include <stdint.h> #include <string.h> #include <dev/random/entropy.h> -#include <dev/random/siphash.h> +#include <crypto/siphash.h> void mix_entropy(struct entropy_pool *ep, const uint8_t *input, diff --git a/sys/dev/random/random.c b/sys/dev/random/random.c index d79df69..9bca719 100644 --- a/sys/dev/random/random.c +++ b/sys/dev/random/random.c @@ -30,9 +30,9 @@ #include <sys/sio.h> #include <sys/device.h> #include <sys/driver.h> -#include <dev/random/chacha20.h> -#include <dev/random/siphash.h> #include <dev/random/entropy.h> +#include <crypto/chacha20.h> +#include <crypto/siphash.h> #include <fs/devfs.h> #include <string.h> diff --git a/sys/include/arch/amd64/cpu.h b/sys/include/arch/amd64/cpu.h index 46e5df7..a047cef 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/sched.h> #include <sys/spinlock.h> #include <machine/tss.h> @@ -45,12 +46,15 @@ struct cpu_info { uint32_t apicid; uint32_t feat; + uint8_t model : 4; /* CPU model number */ + uint8_t family : 4; /* CPU family ID */ 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 sched_cpu stat; struct tss_entry *tss; struct proc *curtd; struct spinlock lock; @@ -65,6 +69,8 @@ void cpu_enable_smep(void); void cpu_disable_smep(void); struct cpu_info *cpu_get(uint32_t index); +struct sched_cpu *cpu_get_stat(uint32_t cpu_index); + uint32_t cpu_count(void); void cpu_shootdown_tlb(vaddr_t va); diff --git a/sys/include/arch/amd64/intr.h b/sys/include/arch/amd64/intr.h index c848b6f..1877d20 100644 --- a/sys/include/arch/amd64/intr.h +++ b/sys/include/arch/amd64/intr.h @@ -69,9 +69,11 @@ struct intr_data { * [r]: Required for intr_register() * [o]: Not required for intr_register() * [v]: Returned by intr_register() + * [i]: Internal * * @func: The actual handler [r] * @data: Interrupt data [o/v] + * @nintr: Number of times it fired [o] * @name: Interrupt name [v] * @priority: Interrupt priority [r] * @irq: Interrupt request number [o] @@ -91,6 +93,7 @@ struct intr_data { */ struct intr_hand { int(*func)(void *); + size_t nintr; struct intr_data data; char *name; int priority; diff --git a/sys/include/dev/random/chacha20.h b/sys/include/crypto/chacha20.h index d35702a..d35702a 100644 --- a/sys/include/dev/random/chacha20.h +++ b/sys/include/crypto/chacha20.h diff --git a/sys/include/dev/random/siphash.h b/sys/include/crypto/siphash.h index ecabb4a..ecabb4a 100644 --- a/sys/include/dev/random/siphash.h +++ b/sys/include/crypto/siphash.h diff --git a/sys/include/dev/mii/mii.h b/sys/include/dev/mii/mii.h new file mode 100644 index 0000000..5d77281 --- /dev/null +++ b/sys/include/dev/mii/mii.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _DEV_MII_H_ +#define _DEV_MII_H_ + +#include <sys/param.h> + +/* + * MII registers + */ +#define MII_BMCR 0x00 /* Basic Mode Config */ +#define MII_BMSR 0x01 /* Basic Mode Status */ +#define MII_PHYID 0x02 /* MII PHY identifier 1 */ +#define MII_PHYID2 0x03 /* MII PHY identifier 2 */ +#define MII_ADVER 0x04 /* Auto-negotiation advertisement */ +#define MII_LPA 0x05 /* Link parter abilities */ +#define MII_EXPAN 0x06 /* Auto-negotiation expansion */ +#define MII_ESTATUS 0x0F /* Extended status register */ +#define MII_IRQ 0x1B /* Interrupt control/status */ + +/* + * MII BMCR bits + */ +#define MII_BMCR_RST BIT(15) /* PHY reset */ +#define MII_BCMR_LOOP BIT(14) /* Loopback mode enable */ +#define MII_BMCR_ANEN BIT(12) /* Auto-negotiation enable */ +#define MII_PWR_DOWN BIT(11) /* Power down PHY */ +#define MII_ISOLATE BIT(10) /* Electrically isolate PHY from MII */ + +#endif /* !_DEV_MII_H_ */ diff --git a/sys/include/dev/phy/et131xregs.h b/sys/include/dev/phy/et131xregs.h new file mode 100644 index 0000000..1f8bfcb --- /dev/null +++ b/sys/include/dev/phy/et131xregs.h @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Please refer to share/docs/hw/et131x.txt + */ + +#ifndef _PHYS_ET131XREGS_H_ +#define _PHYS_ET131XREGS_H_ + +#include <sys/types.h> + +#define MAC_CFG1_SOFTRST 0x80000000 /* Soft reset */ +#define MAC_CFG1_SIMRST 0x40000000 /* SIM reset */ +#define MAC_CFG1_RESET_RXMC 0x00080000 /* RX MC reset */ +#define MAC_CFG1_RESET_TXMC 0x00040000 /* TX MC reset */ +#define MAC_CFG1_RESET_RXFUNC 0x00020000 /* RX func reset */ +#define MAC_CFG1_RESET_TXFUNC 0x00010000 /* TX func reset */ + +#define PAD_N(N, NAME) uint8_t (NAME)[(N)] + +/* + * ET131X global registers + */ +struct global_regs { + uint32_t txq_start; + uint32_t txq_end; + uint32_t rxq_start; + uint32_t rxq_end; + uint32_t pm_csr; + uint32_t unused; + uint32_t istat; + uint32_t imask; + uint32_t ialias_clr_en; + uint32_t istat_alias; + uint32_t sw_reset; + uint32_t slv_timer; + uint32_t msi_config; + uint32_t loopback; + uint32_t watchdog_timer; +}; + +/* + * ET131X TX DMA registers + */ +struct txdma_regs { + uint32_t csr; + uint32_t pr_base_hi; + uint32_t pr_base_lo; + uint32_t pr_num_des; + uint32_t txq_wr_addr; + uint32_t txq_wr_addr_ext; + uint32_t txq_rd_addr; + uint32_t dma_wb_base_hi; + uint32_t dma_wb_base_lo; + uint32_t service_request; + uint32_t service_complete; + uint32_t cache_rd_index; + uint32_t cache_wr_index; + uint32_t tx_dma_error; + uint32_t des_abort_cnt; + uint32_t payload_abort_cnt; + uint32_t wb_abort_cnt; + uint32_t des_timeout_cnt; + uint32_t payload_timeout_cnt; + uint32_t wb_timeout_cnt; + uint32_t des_error_cnt; + uint32_t payload_err_cnt; + uint32_t wb_error_cnt; + uint32_t dropped_tlp_cnt; + uint32_t new_service_complete; + uint32_t ether_pkt_cnt; +}; + +/* + * ET131X RX DMA registers + */ +struct rxdma_regs { + uint32_t csr; + uint32_t dma_wb_base_lo; + uint32_t dma_wb_base_hi; + uint32_t num_pkt_done; + uint32_t max_pkt_time; + uint32_t rxq_rd_addr; + uint32_t rxq_rd_addr_ext; + uint32_t rxq_wr_addr; + uint32_t psr_base_lo; + uint32_t psr_base_hi; + uint32_t psr_num_des; + uint32_t psr_avail_offset; + uint32_t psr_full_offset; + uint32_t psr_access_index; + uint32_t psr_min_des; + uint32_t fbr0_base_lo; + uint32_t fbr0_base_hi; + uint32_t fbr0_num_des; + uint32_t fbr0_avail_offset; + uint32_t fbr0_full_offset; + uint32_t fbr0_rd_index; + uint32_t fbr0_min_des; + uint32_t fbr1_base_lo; + uint32_t fbr1_base_hi; + uint32_t fbr1_num_des; + uint32_t fbr1_avail_offset; + uint32_t fbr1_full_offset; + uint32_t fbr1_rd_index; + uint32_t fbr1_min_des; +}; + +/* + * ET131X TX MAC registers + */ +struct txmac_regs { + uint32_t ctl; + uint32_t shadow_ptr; + uint32_t err_cnt; + uint32_t max_fill; + uint32_t cf_param; + uint32_t tx_test; + uint32_t err; + uint32_t err_int; + uint32_t bp_ctrl; +}; + +/* + * ET131X RX MAC registers + */ +struct rxmac_regs { + uint32_t ctrl; + uint32_t crc0; + uint32_t crc12; + uint32_t crc34; + uint32_t sa_lo; + uint32_t sa_hi; + uint32_t mask0_word0; + uint32_t mask0_word1; + uint32_t mask0_word2; + uint32_t mask0_word3; + uint32_t mask1_word0; + uint32_t mask1_word1; + uint32_t mask1_word2; + uint32_t mask1_word3; + uint32_t mask2_word0; + uint32_t mask2_word1; + uint32_t mask2_word2; + uint32_t mask2_word3; + uint32_t mask3_word0; + uint32_t mask3_word1; + uint32_t mask3_word2; + uint32_t mask3_word3; + uint32_t mask4_word0; + uint32_t mask4_word1; + uint32_t mask4_word2; + uint32_t mask4_word3; + uint32_t uni_pf_addr1; + uint32_t uni_pf_addr2; + uint32_t uni_pf_addr3; + uint32_t multi_hash1; + uint32_t multi_hash2; + uint32_t multi_hash3; + uint32_t multi_hash4; + uint32_t pf_ctrl; + uint32_t mcif_ctrl_max_seg; + uint32_t mcif_water_mark; + uint32_t rxq_diag; + uint32_t space_avail; + uint32_t mif_ctrl; + uint32_t err_reg; +}; + +struct mac_regs { + uint32_t cfg1; + uint32_t cfg2; + uint32_t ipg; + uint32_t hfdp; + uint32_t max_fm_len; + uint32_t rsv1; + uint32_t rsv2; + uint32_t mac_test; + uint32_t mii_mgmt_cfg; + uint32_t mii_mgmt_cmd; + uint32_t mii_mgmt_addr; + uint32_t mii_mgmt_ctrl; + uint32_t mii_mgmt_stat; + uint32_t mii_mgmt_indicator; + uint32_t if_ctrl; + uint32_t if_stat; + uint32_t station_addr_1; + uint32_t station_addr_2; +}; + +/* Global reset */ +#define GBL_RESET_ALL 0x007F + +/* MII management address */ +#define MAC_MII_ADDR(PHY, REG) ((PHY) << 8 | (REG)) + +/* MAC management indications */ +#define MAC_MGMT_BUSY 0x00000001 +#define MAC_MGMT_WAIT 0x00000005 + +/* MAC management config values */ +#define MAC_MIIMGMT_CLK_RST 0x00007 + +/* LED register defines */ +#define PHY_LED2 0x1C + +/* PCI config space offsets */ +#define PCI_EEPROM_STATUS 0xB2 +#define PCI_MAC_ADDRESS 0xA4 + +/* + * LED control register 2 values + */ +#define LED_BLINK 0xD +#define LED_ON 0xE +#define LED_OFF 0xF +#define LED_ALL_OFF 0xFFFF + +/* + * LED register bit-shift constants + * + * Bits [3:0]: 100BASE-T LED + * Bits [7:4]: 100BASE-TX LED + * Bits [11:8]: TX/RX LED + * Bits [15:12]: Link LED + */ +#define LED_TXRX_SHIFT 8 +#define LED_LINK_SHIFT 12 + +struct et131x_iospace { +#define _IO_PAD(NAME, REGSET) uint8_t NAME[4096 - sizeof(struct REGSET)] + struct global_regs global; + _IO_PAD(global_pad, global_regs); + struct txdma_regs txdma; + _IO_PAD(txdma_pad, txdma_regs); + struct rxdma_regs rxdma; + _IO_PAD(rxdma_pad, rxdma_regs); + struct txmac_regs txmac; + _IO_PAD(txmac_pad, txmac_regs); + struct rxmac_regs rxmac; + _IO_PAD(rxmac_pad, rxmac_regs); + struct mac_regs mac; + _IO_PAD(mac_pad, mac_regs); + /* ... TODO - add more */ +#undef _IO_PAD +}; + +#endif /* !_PHYS_ET131XREGS_H_ */ diff --git a/sys/include/sys/atomic.h b/sys/include/sys/atomic.h index f61bf62..d9b3bde 100644 --- a/sys/include/sys/atomic.h +++ b/sys/include/sys/atomic.h @@ -30,6 +30,8 @@ #ifndef _SYS_ATOMIC_H_ #define _SYS_ATOMIC_H_ +#include <sys/types.h> + static inline unsigned long atomic_add_long_nv(volatile unsigned long *p, unsigned long v) { @@ -42,6 +44,12 @@ atomic_add_int_nv(volatile unsigned int *p, unsigned int v) return __sync_add_and_fetch(p, v); } +static inline unsigned int +atomic_add_64_nv(volatile uint64_t *p, unsigned int v) +{ + return __sync_add_and_fetch(p, v); +} + static inline unsigned long atomic_sub_long_nv(volatile unsigned long *p, unsigned long v) { @@ -55,6 +63,12 @@ atomic_sub_int_nv(volatile unsigned int *p, unsigned int v) } static inline unsigned int +atomic_sub_64_nv(volatile uint64_t *p, unsigned int v) +{ + return __sync_sub_and_fetch(p, v); +} + +static inline unsigned int atomic_load_int_nv(volatile unsigned int *p, unsigned int v) { return __atomic_load_n(p, v); @@ -66,6 +80,12 @@ atomic_load_long_nv(volatile unsigned long *p, unsigned int v) return __atomic_load_n(p, v); } +static inline unsigned int +atomic_load_64_nv(volatile uint64_t *p, unsigned int v) +{ + return __atomic_load_n(p, v); +} + static inline void atomic_store_int_nv(volatile unsigned int *p, int nv, unsigned int v) { @@ -78,20 +98,30 @@ atomic_store_long_nv(volatile unsigned long *p, long nv, unsigned int v) __atomic_store_n(p, nv, v); } +static inline void +atomic_store_64_nv(volatile uint64_t *p, long nv, unsigned int v) +{ + __atomic_store_n(p, nv, v); +} + /* Atomic increment (and fetch) operations */ #define atomic_inc_long(P) atomic_add_long_nv((P), 1) #define atomic_inc_int(P) atomic_add_int_nv((P), 1) +#define atomic_inc_64(P) atomic_add_64_nv((P), 1) /* Atomic decrement (and fetch) operations */ #define atomic_dec_long(P) atomic_sub_long_nv((P), 1) #define atomic_dec_int(P) atomic_sub_int_nv((P), 1) +#define atomic_dec_64(P) atomic_sub_64_nv((P), 1) /* Atomic load operations */ #define atomic_load_int(P) atomic_load_int_nv((P), __ATOMIC_SEQ_CST) #define atomic_load_long(P) atomic_load_long_nv((P), __ATOMIC_SEQ_CST) +#define atomic_load_64(P) atomic_load_64_nv((P), __ATOMIC_SEQ_CST) /* Atomic store operations */ #define atomic_store_int(P, NV) atomic_store_int_nv((P), (NV), __ATOMIC_SEQ_CST) #define atomic_store_long(P, NV) atomic_store_long_nv((P), (NV), __ATOMIC_SEQ_CST) +#define atomic_store_64(P, NV) atomic_store_64_nv((P), (NV), __ATOMIC_SEQ_CST) #endif /* !_SYS_ATOMIC_H_ */ diff --git a/sys/include/sys/limits.h b/sys/include/sys/limits.h index 5b97b68..f6aed9d 100644 --- a/sys/include/sys/limits.h +++ b/sys/include/sys/limits.h @@ -35,7 +35,5 @@ #define SSIZE_MAX 32767 #define ARG_MAX 4096 #define CHAR_BIT 8 -#if defined(_KERNEL) #define CPU_MAX 256 -#endif /* _KERNEL */ #endif /* !_SYS_LIMITS_H_ */ diff --git a/sys/include/sys/sched.h b/sys/include/sys/sched.h index 7d17607..abc2718 100644 --- a/sys/include/sys/sched.h +++ b/sys/include/sys/sched.h @@ -32,13 +32,38 @@ #include <sys/proc.h> #include <sys/cdefs.h> +#include <sys/limits.h> + +/* + * Scheduler CPU information + * + * @nswitch: Number of context switches + * @idle: Number of milliseconds idle + */ +struct sched_cpu { + uint32_t nswitch; +}; + +/* + * Scheduler statistics + * + * @nproc: Number processes running + * @ncpu: Number of CPU cores + * @quantum_usec: Scheduler quantum (microseconds) + */ +struct sched_stat { + size_t nproc; + uint16_t ncpu; + uint32_t quantum_usec; + struct sched_cpu cpus[CPU_MAX]; +}; #if defined(_KERNEL) +void sched_stat(struct sched_stat *statp); void sched_init(void); -void sched_yield(void); -void sched_switch_to(struct trapframe *tf, struct proc *td); +void sched_yield(void); void sched_detach(struct proc *td); __dead void sched_enter(void); diff --git a/sys/include/sys/schedvar.h b/sys/include/sys/schedvar.h index 5ed9f5f..017fcb7 100644 --- a/sys/include/sys/schedvar.h +++ b/sys/include/sys/schedvar.h @@ -60,5 +60,11 @@ struct sched_queue { size_t nthread; }; +struct proc *sched_dequeue_td(void); +void mi_sched_switch(struct proc *from); + +void md_sched_switch(struct trapframe *tf); +void sched_oneshot(bool now); + #endif /* _KERNEL */ #endif /* !_SYS_SCHEDVAR_H_ */ diff --git a/sys/kern/kern_accnt.c b/sys/kern/kern_accnt.c new file mode 100644 index 0000000..cd15863 --- /dev/null +++ b/sys/kern/kern_accnt.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * System Accounting + */ + +#include <sys/sched.h> +#include <sys/schedvar.h> +#include <sys/proc.h> +#include <fs/ctlfs.h> +#include <machine/cpu.h> +#include <string.h> + +/* Called within kern_sched.c */ +void sched_accnt_init(void); + +static struct ctlops sched_stat_ctl; +volatile size_t g_nthreads; + +static int +ctl_stat_read(struct ctlfs_dev *cdp, struct sio_txn *sio) +{ + struct sched_stat stat; + + if (sio->len > sizeof(stat)) { + sio->len = sizeof(stat); + } + + sched_stat(&stat); + memcpy(sio->buf, &stat, sio->len); + return sio->len; +} + +/* + * Get scheduler accounting information + * + * @statp: Info gets copied here + */ +void +sched_stat(struct sched_stat *statp) +{ + struct sched_cpu *cpustat; + + statp->nproc = atomic_load_64(&g_nthreads); + statp->ncpu = cpu_count(); + statp->quantum_usec = DEFAULT_TIMESLICE_USEC; + + /* + * Setup the per-cpu info/statistics + */ + for (int i = 0; i < CPU_MAX; ++i) { + cpustat = cpu_get_stat(i); + if (cpustat == NULL) { + break; + } + + statp->cpus[i] = *cpustat; + } +} + +void +sched_accnt_init(void) +{ + char devname[] = "sched"; + struct ctlfs_dev ctl; + + /* + * Register some accounting information in + * '/ctl/sched/stat' + */ + ctl.mode = 0444; + ctlfs_create_node(devname, &ctl); + ctl.devname = devname; + ctl.ops = &sched_stat_ctl; + ctlfs_create_entry("stat", &ctl); +} + +static struct ctlops sched_stat_ctl = { + .read = ctl_stat_read, + .write = NULL +}; diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index b5ff144..57beaf6 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -154,6 +154,10 @@ fd_rw(unsigned int fd, void *buf, size_t count, uint8_t write) struct sio_txn sio; scret_t retval = 0; + if (fd > PROC_MAX_FILEDES) { + return -EBADF; + } + if (count > SSIZE_MAX) { retval = -EINVAL; goto done; diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 2c9e2e4..6b41cbd 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -30,6 +30,7 @@ #include <sys/proc.h> #include <sys/sched.h> #include <sys/syslog.h> +#include <sys/atomic.h> #include <sys/panic.h> #include <sys/filedesc.h> #include <sys/vnode.h> @@ -44,6 +45,8 @@ #define pr_trace(fmt, ...) kprintf("exit: " fmt, ##__VA_ARGS__) #define pr_error(...) pr_trace(__VA_ARGS__) +extern volatile size_t g_nthreads; + static void unload_td(struct proc *td) { @@ -150,6 +153,9 @@ exit1(struct proc *td, int flags) td->flags |= PROC_EXITING; parent = td->parent; + /* We have one less process in the system! */ + atomic_dec_64(&g_nthreads); + /* If we have any children, kill them too */ if (td->nleaves > 0) { TAILQ_FOREACH(procp, &td->leafq, leaf_link) { diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index 24806db..e259a2c 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -45,7 +45,8 @@ #define pr_trace(fmt, ...) kprintf("ksched: " fmt, ##__VA_ARGS__) -void sched_switch(struct trapframe *tf); +void md_sched_switch(struct trapframe *tf); +void sched_accnt_init(void); static sched_policy_t policy = SCHED_POLICY_MLFQ; @@ -64,7 +65,7 @@ __cacheline_aligned static struct spinlock tdq_lock = {0}; /* * Perform timer oneshot */ -static inline void +void sched_oneshot(bool now) { struct timer timer; @@ -77,25 +78,7 @@ sched_oneshot(bool now) timer.oneshot_us(usec); } -/* - * Save thread state and enqueue it back into one - * of the ready queues. - */ -static void -sched_save_td(struct proc *td, struct trapframe *tf) -{ - /* - * Save trapframe to process structure only - * if PROC_EXEC is not set. - */ - if (!ISSET(td->flags, PROC_EXEC)) { - memcpy(&td->tf, tf, sizeof(td->tf)); - } - - sched_enqueue_td(td); -} - -static struct proc * +struct proc * sched_dequeue_td(void) { struct sched_queue *queue; @@ -197,52 +180,22 @@ 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. + * MI work to be done during a context + * switch. Called by md_sched_switch() */ void -sched_switch(struct trapframe *tf) +mi_sched_switch(struct proc *from) { - struct proc *next_td, *td; - struct cpu_info *ci; - - ci = this_cpu(); - td = ci->curtd; - cons_detach(); - - if (td != NULL) { - if (td->pid == 0) + if (from != NULL) { + if (from->pid == 0) return; - dispatch_signals(td); - td_pri_update(td); - sched_save_td(td, tf); - } - - if ((next_td = sched_dequeue_td()) == NULL) { - sched_oneshot(false); - return; + dispatch_signals(from); + td_pri_update(from); } - sched_switch_to(tf, next_td); - sched_oneshot(false); + cons_detach(); } /* @@ -306,4 +259,6 @@ sched_init(void) pr_trace("prepared %d queues (policy=0x%x)\n", SCHED_NQUEUE, policy); + + sched_accnt_init(); } diff --git a/sys/kern/kern_spawn.c b/sys/kern/kern_spawn.c index fcaa194..75ebaa7 100644 --- a/sys/kern/kern_spawn.c +++ b/sys/kern/kern_spawn.c @@ -33,6 +33,7 @@ #include <sys/mman.h> #include <sys/systm.h> #include <sys/errno.h> +#include <sys/atomic.h> #include <sys/syslog.h> #include <sys/syscall.h> #include <sys/atomic.h> @@ -47,7 +48,8 @@ #define ARGVP_MAX (ARG_MAX / sizeof(void *)) -static volatile size_t nthreads = 0; +static size_t next_pid = 1; +extern volatile size_t g_nthreads; /* * TODO: envp @@ -166,7 +168,8 @@ spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **new newproc->mlgdr = mlgdr; newproc->flags |= PROC_WAITED; - newproc->pid = ++nthreads; + atomic_inc_64(&g_nthreads); + newproc->pid = next_pid++; signals_init(newproc); sched_enqueue_td(newproc); pid = newproc->pid; |