Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions include/lttle/trigger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef _LTTLE_TRIGGER_H
#define _LTTLE_TRIGGER_H

#include <linux/io.h>

#define LTTLE_TRIGGER_MEMORY_BASE (0xd0000000)
#define LTTLE_TRIGGER_MEMORY_SIZE (4096)

#define LTTLE_SYS_AFTER_OFFSET 127
#define LTTLE_SYS_CMD_OFFSET 64

#define LTTLE_SYS_LISTEN_BEFORE 1
#define LTTLE_SYS_BIND_BEFORE 2
#define LTTLE_USERSPACE_READY 3
#define LTTLE_MANUAL_TRIGGER 10

#define LTTLE_SYS_LISTEN_AFTER (LTTLE_SYS_LISTEN_BEFORE + LTTLE_SYS_AFTER_OFFSET)
#define LTTLE_SYS_BIND_AFTER (LTTLE_SYS_BIND_BEFORE + LTTLE_SYS_AFTER_OFFSET)

#define LTTLE_CMD_FLASH_LOCK (LTTLE_SYS_CMD_OFFSET + 0)
#define LTTLE_CMD_FLASH_UNLOCK (LTTLE_SYS_CMD_OFFSET + 1)

int __init lttle_subsystem_init(void);
void __exit lttle_subsystem_exit(void);
void lttle_sys_trigger(unsigned char code, char data[7]);
void lttle_sys_cmd(unsigned char cmd);

#endif // _LTTLE_TRIGGER_H
3 changes: 2 additions & 1 deletion kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ obj-y = fork.o exec_domain.o panic.o \
extable.o params.o \
kthread.o sys_ni.o nsproxy.o \
notifier.o ksysfs.o cred.o reboot.o \
async.o range.o smpboot.o ucount.o regset.o
async.o range.o smpboot.o ucount.o regset.o \
lttle.o

obj-$(CONFIG_USERMODE_DRIVER) += usermode_driver.o
obj-$(CONFIG_MODULES) += kmod.o
Expand Down
134 changes: 134 additions & 0 deletions kernel/lttle.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#include <lttle/trigger.h>

#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/printk.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/string.h>

static volatile void *mapped_mmio_base = 0;

typedef struct {
unsigned char code;
// 7 bytes data
unsigned char data[7];
} lttle_sys_trigger_data;

typedef char lttle_sys_trigger_data_incomplete_size[sizeof(lttle_sys_trigger_data) == 8 ? 1 : -1]; // Ensure the size of the struct is 8 bytes

static ssize_t lttle_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
unsigned long long last_boot_time = (*(volatile unsigned long long *)mapped_mmio_base);
unsigned long long first_boot_time = (*(volatile unsigned long long *)(mapped_mmio_base + 8));
char msg[1024];
int len = snprintf(msg, sizeof(msg), "{\"last_boot_time_us\": %llu, \"first_boot_time_us\": %llu}", last_boot_time, first_boot_time);

return simple_read_from_buffer(buf, count, ppos, msg, len);
}

static ssize_t lttle_proc_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
int len;
char tbuf[256] = {0};

if (count >= sizeof(tbuf)) {
return -ENOSPC;
}

len = simple_write_to_buffer(tbuf, sizeof(tbuf) - 1, ppos, buf, count);
if (len < 0) {
return len;
}

tbuf[len] = '\0';

if (strcmp(tbuf, "manual_trigger") == 0) {
lttle_sys_trigger(LTTLE_MANUAL_TRIGGER, NULL);
*ppos = 0; // Reset position for next write
return count;
}

if (strcmp(tbuf, "flash_lock") == 0) {
lttle_sys_cmd(LTTLE_CMD_FLASH_LOCK);
*ppos = 0; // Reset position for next write
return count;
}

if (strcmp(tbuf, "flash_unlock") == 0) {
lttle_sys_cmd(LTTLE_CMD_FLASH_UNLOCK);
*ppos = 0; // Reset position for next write
return count;
}

*ppos = 0; // Reset position for next write
return count;
}

static const struct proc_ops lttle_proc_ops = {
.proc_read = lttle_proc_read,
.proc_write = lttle_proc_write,
};

static struct proc_dir_entry *lttle_proc_entry;

int __init lttle_subsystem_init(void)
{
mapped_mmio_base = ioremap(LTTLE_TRIGGER_MEMORY_BASE, LTTLE_TRIGGER_MEMORY_SIZE);
if (!mapped_mmio_base) {
pr_err("Failed to map MMIO region for LTTLE subsystem\n");
return -1;
}

lttle_proc_entry = proc_create("lttle", 0666, NULL, &lttle_proc_ops);
if (!lttle_proc_entry) {
pr_err("Failed to create /proc/lttle\n");
iounmap(mapped_mmio_base);
mapped_mmio_base = 0;
return -1;
}

pr_info("LTTLE subsystem initialized, MMIO base mapped at %px\n", mapped_mmio_base);
return 0;
}

void __exit lttle_subsystem_exit(void)
{
if (lttle_proc_entry) {
proc_remove(lttle_proc_entry);
lttle_proc_entry = NULL;
}
if (mapped_mmio_base) {
iounmap(mapped_mmio_base);
pr_info("LTTLE subsystem MMIO region unmapped\n");
mapped_mmio_base = 0;
}

pr_info("LTTLE subsystem exited cleanly\n");
}

void lttle_sys_trigger(unsigned char code, char data[7])
{
lttle_sys_trigger_data trigger_data;
trigger_data.code = code;
if (data) {
memcpy(trigger_data.data, data, sizeof(trigger_data.data));
}

if (!mapped_mmio_base) {
pr_err("MMIO base not mapped. Did you call lttle_sys_trigger_init()?\n");
return;
}


*((volatile lttle_sys_trigger_data *)mapped_mmio_base) = trigger_data;
}

void lttle_sys_cmd(unsigned char cmd)
{
*((volatile unsigned char *)mapped_mmio_base + 8) = cmd;
}

subsys_initcall(lttle_subsystem_init);
module_exit(lttle_subsystem_exit);
56 changes: 55 additions & 1 deletion net/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@
#include <linux/errqueue.h>
#include <linux/ptp_clock_kernel.h>

#include <lttle/trigger.h>

#ifdef CONFIG_NET_RX_BUSY_POLL
unsigned int sysctl_net_busy_read __read_mostly;
unsigned int sysctl_net_busy_poll __read_mostly;
Expand Down Expand Up @@ -1632,6 +1634,7 @@ int __sys_socket(int family, int type, int protocol)
{
struct socket *sock;
int flags;
int fd;

sock = __sys_socket_create(family, type, protocol);
if (IS_ERR(sock))
Expand All @@ -1641,7 +1644,8 @@ int __sys_socket(int family, int type, int protocol)
if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;

return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
fd = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
return fd;
}

SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
Expand Down Expand Up @@ -1763,12 +1767,34 @@ int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
{
struct socket *sock;
struct sockaddr_storage address;
struct sockaddr *addr;
struct sockaddr_in *addr_in;
int err, fput_needed;
bool compatible_family_trigger = false;
char trigger_data[7] = {0};

sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock) {
err = move_addr_to_kernel(umyaddr, addrlen, &address);
if (!err) {
addr = (struct sockaddr *)&address;
if (addr->sa_family == AF_INET) {
compatible_family_trigger = true;
addr_in = (struct sockaddr_in *)addr;

// trigger_data[0..1] = port
trigger_data[0] = addr_in->sin_port >> 8;
trigger_data[1] = addr_in->sin_port & 0xFF;

// // trigger_data[2..5] = address
trigger_data[2] = addr_in->sin_addr.s_addr >> 24;
trigger_data[3] = addr_in->sin_addr.s_addr >> 16;
trigger_data[4] = addr_in->sin_addr.s_addr >> 8;
trigger_data[5] = addr_in->sin_addr.s_addr;

lttle_sys_trigger(LTTLE_SYS_BIND_BEFORE, trigger_data);
}

err = security_socket_bind(sock,
(struct sockaddr *)&address,
addrlen);
Expand All @@ -1779,6 +1805,11 @@ int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
}
fput_light(sock->file, fput_needed);
}

if (err == 0 && compatible_family_trigger) {
lttle_sys_trigger(LTTLE_SYS_BIND_AFTER, trigger_data);
}

return err;
}

Expand All @@ -1798,9 +1829,27 @@ int __sys_listen(int fd, int backlog)
struct socket *sock;
int err, fput_needed;
int somaxconn;
bool compatible_family_trigger = false;
char trigger_data[7] = {0};

sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock) {
if (sock->sk) {
compatible_family_trigger = true;

// trigger_data[0..1] = port (local port for listening socket)
trigger_data[0] = sock->sk->sk_num & 0xFF;
trigger_data[1] = sock->sk->sk_num >> 8;
// trigger_data[2..5] = address (local address)
trigger_data[2] = sock->sk->sk_rcv_saddr >> 24;
trigger_data[3] = sock->sk->sk_rcv_saddr >> 16;
trigger_data[4] = sock->sk->sk_rcv_saddr >> 8;
trigger_data[5] = sock->sk->sk_rcv_saddr;

lttle_sys_trigger(LTTLE_SYS_LISTEN_BEFORE, trigger_data);
}


somaxconn = READ_ONCE(sock_net(sock->sk)->core.sysctl_somaxconn);
if ((unsigned int)backlog > somaxconn)
backlog = somaxconn;
Expand All @@ -1811,6 +1860,11 @@ int __sys_listen(int fd, int backlog)

fput_light(sock->file, fput_needed);
}

if (err == 0 && compatible_family_trigger) {
lttle_sys_trigger(LTTLE_SYS_LISTEN_AFTER, trigger_data);
}

return err;
}

Expand Down