Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f1f54b4216 | ||
be5a41ecb0 | |||
![]() |
31e51513fb | ||
![]() |
0e52191467 | ||
![]() |
07fad299b8 | ||
![]() |
b1ac2df90e | ||
![]() |
e63dd18335 |
32
a1.1.config
32
a1.1.config
@ -1,20 +1,21 @@
|
|||||||
#
|
#
|
||||||
# Automatically generated file; DO NOT EDIT.
|
# Automatically generated file; DO NOT EDIT.
|
||||||
# Linux/x86 6.1.55 Kernel Configuration
|
# Linux/x86 6.1.134 Kernel Configuration
|
||||||
#
|
#
|
||||||
CONFIG_CC_VERSION_TEXT="gcc (Debian 13.2.0-23) 13.2.0"
|
CONFIG_CC_VERSION_TEXT="gcc (Debian 12.2.0-14) 12.2.0"
|
||||||
CONFIG_CC_IS_GCC=y
|
CONFIG_CC_IS_GCC=y
|
||||||
CONFIG_GCC_VERSION=130200
|
CONFIG_GCC_VERSION=120200
|
||||||
CONFIG_CLANG_VERSION=0
|
CONFIG_CLANG_VERSION=0
|
||||||
CONFIG_AS_IS_GNU=y
|
CONFIG_AS_IS_GNU=y
|
||||||
CONFIG_AS_VERSION=24200
|
CONFIG_AS_VERSION=24000
|
||||||
CONFIG_LD_IS_BFD=y
|
CONFIG_LD_IS_BFD=y
|
||||||
CONFIG_LD_VERSION=24200
|
CONFIG_LD_VERSION=24000
|
||||||
CONFIG_LLD_VERSION=0
|
CONFIG_LLD_VERSION=0
|
||||||
CONFIG_CC_CAN_LINK=y
|
CONFIG_CC_CAN_LINK=y
|
||||||
CONFIG_CC_CAN_LINK_STATIC=y
|
CONFIG_CC_CAN_LINK_STATIC=y
|
||||||
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
|
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
|
||||||
CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
|
CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
|
||||||
|
CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y
|
||||||
CONFIG_CC_HAS_ASM_INLINE=y
|
CONFIG_CC_HAS_ASM_INLINE=y
|
||||||
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
|
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
|
||||||
CONFIG_PAHOLE_VERSION=124
|
CONFIG_PAHOLE_VERSION=124
|
||||||
@ -175,7 +176,7 @@ CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
|
|||||||
CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
|
CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
|
||||||
CONFIG_CC_HAS_INT128=y
|
CONFIG_CC_HAS_INT128=y
|
||||||
CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5"
|
CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5"
|
||||||
CONFIG_GCC11_NO_ARRAY_BOUNDS=y
|
CONFIG_GCC10_NO_ARRAY_BOUNDS=y
|
||||||
CONFIG_CC_NO_ARRAY_BOUNDS=y
|
CONFIG_CC_NO_ARRAY_BOUNDS=y
|
||||||
CONFIG_ARCH_SUPPORTS_INT128=y
|
CONFIG_ARCH_SUPPORTS_INT128=y
|
||||||
# CONFIG_NUMA_BALANCING is not set
|
# CONFIG_NUMA_BALANCING is not set
|
||||||
@ -428,6 +429,7 @@ CONFIG_X86_INTEL_TSX_MODE_OFF=y
|
|||||||
# CONFIG_X86_INTEL_TSX_MODE_AUTO is not set
|
# CONFIG_X86_INTEL_TSX_MODE_AUTO is not set
|
||||||
CONFIG_EFI=y
|
CONFIG_EFI=y
|
||||||
CONFIG_EFI_STUB=y
|
CONFIG_EFI_STUB=y
|
||||||
|
# CONFIG_EFI_HANDOVER_PROTOCOL is not set
|
||||||
CONFIG_EFI_MIXED=y
|
CONFIG_EFI_MIXED=y
|
||||||
# CONFIG_HZ_100 is not set
|
# CONFIG_HZ_100 is not set
|
||||||
# CONFIG_HZ_250 is not set
|
# CONFIG_HZ_250 is not set
|
||||||
@ -461,7 +463,7 @@ CONFIG_HAVE_LIVEPATCH=y
|
|||||||
|
|
||||||
CONFIG_CC_HAS_SLS=y
|
CONFIG_CC_HAS_SLS=y
|
||||||
CONFIG_CC_HAS_RETURN_THUNK=y
|
CONFIG_CC_HAS_RETURN_THUNK=y
|
||||||
# CONFIG_SPECULATION_MITIGATIONS is not set
|
# CONFIG_CPU_MITIGATIONS is not set
|
||||||
CONFIG_ARCH_HAS_ADD_PAGES=y
|
CONFIG_ARCH_HAS_ADD_PAGES=y
|
||||||
CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y
|
CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y
|
||||||
|
|
||||||
@ -618,6 +620,7 @@ CONFIG_AS_AVX512=y
|
|||||||
CONFIG_AS_SHA1_NI=y
|
CONFIG_AS_SHA1_NI=y
|
||||||
CONFIG_AS_SHA256_NI=y
|
CONFIG_AS_SHA256_NI=y
|
||||||
CONFIG_AS_TPAUSE=y
|
CONFIG_AS_TPAUSE=y
|
||||||
|
CONFIG_ARCH_CONFIGURES_CPU_MITIGATIONS=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# General architecture-dependent options
|
# General architecture-dependent options
|
||||||
@ -865,6 +868,7 @@ CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
|
|||||||
CONFIG_PAGE_REPORTING=y
|
CONFIG_PAGE_REPORTING=y
|
||||||
CONFIG_MIGRATION=y
|
CONFIG_MIGRATION=y
|
||||||
CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y
|
CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y
|
||||||
|
CONFIG_PCP_BATCH_SCALE_MAX=5
|
||||||
CONFIG_PHYS_ADDR_T_64BIT=y
|
CONFIG_PHYS_ADDR_T_64BIT=y
|
||||||
CONFIG_MMU_NOTIFIER=y
|
CONFIG_MMU_NOTIFIER=y
|
||||||
# CONFIG_KSM is not set
|
# CONFIG_KSM is not set
|
||||||
@ -1129,7 +1133,6 @@ CONFIG_NET_SCHED=y
|
|||||||
#
|
#
|
||||||
# Queueing/Scheduling
|
# Queueing/Scheduling
|
||||||
#
|
#
|
||||||
# CONFIG_NET_SCH_CBQ is not set
|
|
||||||
# CONFIG_NET_SCH_HTB is not set
|
# CONFIG_NET_SCH_HTB is not set
|
||||||
# CONFIG_NET_SCH_HFSC is not set
|
# CONFIG_NET_SCH_HFSC is not set
|
||||||
# CONFIG_NET_SCH_PRIO is not set
|
# CONFIG_NET_SCH_PRIO is not set
|
||||||
@ -1143,7 +1146,6 @@ CONFIG_NET_SCHED=y
|
|||||||
# CONFIG_NET_SCH_ETF is not set
|
# CONFIG_NET_SCH_ETF is not set
|
||||||
# CONFIG_NET_SCH_TAPRIO is not set
|
# CONFIG_NET_SCH_TAPRIO is not set
|
||||||
# CONFIG_NET_SCH_GRED is not set
|
# CONFIG_NET_SCH_GRED is not set
|
||||||
# CONFIG_NET_SCH_DSMARK is not set
|
|
||||||
# CONFIG_NET_SCH_NETEM is not set
|
# CONFIG_NET_SCH_NETEM is not set
|
||||||
# CONFIG_NET_SCH_DRR is not set
|
# CONFIG_NET_SCH_DRR is not set
|
||||||
# CONFIG_NET_SCH_MQPRIO is not set
|
# CONFIG_NET_SCH_MQPRIO is not set
|
||||||
@ -1284,8 +1286,6 @@ CONFIG_ETHTOOL_NETLINK=y
|
|||||||
#
|
#
|
||||||
# Device Drivers
|
# Device Drivers
|
||||||
#
|
#
|
||||||
CONFIG_HAVE_EISA=y
|
|
||||||
# CONFIG_EISA is not set
|
|
||||||
CONFIG_HAVE_PCI=y
|
CONFIG_HAVE_PCI=y
|
||||||
CONFIG_PCI=y
|
CONFIG_PCI=y
|
||||||
CONFIG_PCI_DOMAINS=y
|
CONFIG_PCI_DOMAINS=y
|
||||||
@ -1899,9 +1899,6 @@ CONFIG_E1000E_HWTS=y
|
|||||||
# CONFIG_ICE is not set
|
# CONFIG_ICE is not set
|
||||||
# CONFIG_FM10K is not set
|
# CONFIG_FM10K is not set
|
||||||
# CONFIG_IGC is not set
|
# CONFIG_IGC is not set
|
||||||
CONFIG_NET_VENDOR_WANGXUN=y
|
|
||||||
# CONFIG_NGBE is not set
|
|
||||||
# CONFIG_TXGBE is not set
|
|
||||||
# CONFIG_JME is not set
|
# CONFIG_JME is not set
|
||||||
CONFIG_NET_VENDOR_LITEX=y
|
CONFIG_NET_VENDOR_LITEX=y
|
||||||
CONFIG_NET_VENDOR_MARVELL=y
|
CONFIG_NET_VENDOR_MARVELL=y
|
||||||
@ -2003,6 +2000,9 @@ CONFIG_NET_VENDOR_VERTEXCOM=y
|
|||||||
CONFIG_NET_VENDOR_VIA=y
|
CONFIG_NET_VENDOR_VIA=y
|
||||||
# CONFIG_VIA_RHINE is not set
|
# CONFIG_VIA_RHINE is not set
|
||||||
# CONFIG_VIA_VELOCITY is not set
|
# CONFIG_VIA_VELOCITY is not set
|
||||||
|
CONFIG_NET_VENDOR_WANGXUN=y
|
||||||
|
# CONFIG_NGBE is not set
|
||||||
|
# CONFIG_TXGBE is not set
|
||||||
CONFIG_NET_VENDOR_WIZNET=y
|
CONFIG_NET_VENDOR_WIZNET=y
|
||||||
# CONFIG_WIZNET_W5100 is not set
|
# CONFIG_WIZNET_W5100 is not set
|
||||||
# CONFIG_WIZNET_W5300 is not set
|
# CONFIG_WIZNET_W5300 is not set
|
||||||
@ -2915,7 +2915,6 @@ CONFIG_BCMA_POSSIBLE=y
|
|||||||
# CONFIG_MFD_SM501 is not set
|
# CONFIG_MFD_SM501 is not set
|
||||||
# CONFIG_MFD_SKY81452 is not set
|
# CONFIG_MFD_SKY81452 is not set
|
||||||
# CONFIG_MFD_SYSCON is not set
|
# CONFIG_MFD_SYSCON is not set
|
||||||
# CONFIG_MFD_TI_AM335X_TSCADC is not set
|
|
||||||
# CONFIG_MFD_LP3943 is not set
|
# CONFIG_MFD_LP3943 is not set
|
||||||
# CONFIG_MFD_LP8788 is not set
|
# CONFIG_MFD_LP8788 is not set
|
||||||
# CONFIG_MFD_TI_LMU is not set
|
# CONFIG_MFD_TI_LMU is not set
|
||||||
@ -3941,6 +3940,9 @@ CONFIG_KEYS=y
|
|||||||
# CONFIG_ENCRYPTED_KEYS is not set
|
# CONFIG_ENCRYPTED_KEYS is not set
|
||||||
# CONFIG_KEY_DH_OPERATIONS is not set
|
# CONFIG_KEY_DH_OPERATIONS is not set
|
||||||
# CONFIG_SECURITY_DMESG_RESTRICT is not set
|
# CONFIG_SECURITY_DMESG_RESTRICT is not set
|
||||||
|
CONFIG_PROC_MEM_ALWAYS_FORCE=y
|
||||||
|
# CONFIG_PROC_MEM_FORCE_PTRACE is not set
|
||||||
|
# CONFIG_PROC_MEM_NO_FORCE is not set
|
||||||
CONFIG_SECURITY=y
|
CONFIG_SECURITY=y
|
||||||
CONFIG_SECURITY_WRITABLE_HOOKS=y
|
CONFIG_SECURITY_WRITABLE_HOOKS=y
|
||||||
# CONFIG_SECURITYFS is not set
|
# CONFIG_SECURITYFS is not set
|
||||||
|
4686
a1.2.config
4686
a1.2.config
File diff suppressed because it is too large
Load Diff
10
a1.2.txt
10
a1.2.txt
@ -1,10 +0,0 @@
|
|||||||
1) a) um debug beim start des kerns zu aktivieren, reicht kern parameter (mit hilfe -a im unserem skript) zu geben dyndbg=\"module sst_chrdev +p\"
|
|
||||||
b) gleiche idee aber statt module zu wählen, kann mann eine file und zeile auswählen wie z.B
|
|
||||||
dyndbg=\"file sst_chrdev.c line 40 +p; file sst_chrdev.c line 72 +p\"
|
|
||||||
|
|
||||||
2) Mein grundlegendes Verständnis davon, wie kmemleak funktioniert, ist, dass jede neue Speicherzuweisung und ihre Zeiger zusammen mit einer Vielzahl von Metainformationen wie Größe verfolgt werden.
|
|
||||||
Informationen wie z.B. der Größe verfolgt und in einer Baumstruktur (rbtree) gespeichert wird.
|
|
||||||
einen Memory Allocator existiert, bedeutet dies, dass der Kernel nicht mehr in der Lage ist, ihn zu zerstören und er wird als Orphan bezeichnet.
|
|
||||||
|
|
||||||
|
|
||||||
3) um detector standardmäßige auszuschalten, kann mann CONFIG_DEBUG_KMEMLEAK=n setzen oder entfernen im kconfig
|
|
4684
a1.3.config
4684
a1.3.config
File diff suppressed because it is too large
Load Diff
4684
a1.4.config
4684
a1.4.config
File diff suppressed because it is too large
Load Diff
@ -239,6 +239,4 @@ source "drivers/peci/Kconfig"
|
|||||||
|
|
||||||
source "drivers/hte/Kconfig"
|
source "drivers/hte/Kconfig"
|
||||||
|
|
||||||
source "drivers/sst/Kconfig"
|
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
@ -189,4 +189,3 @@ obj-$(CONFIG_COUNTER) += counter/
|
|||||||
obj-$(CONFIG_MOST) += most/
|
obj-$(CONFIG_MOST) += most/
|
||||||
obj-$(CONFIG_PECI) += peci/
|
obj-$(CONFIG_PECI) += peci/
|
||||||
obj-$(CONFIG_HTE) += hte/
|
obj-$(CONFIG_HTE) += hte/
|
||||||
obj-$(CONFIG_SST) += sst/
|
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#include <net/route.h>
|
#include <net/route.h>
|
||||||
#include <net/xdp.h>
|
#include <net/xdp.h>
|
||||||
#include <net/net_failover.h>
|
#include <net/net_failover.h>
|
||||||
#include <linux/sst.h>
|
|
||||||
|
|
||||||
static int napi_weight = NAPI_POLL_WEIGHT;
|
static int napi_weight = NAPI_POLL_WEIGHT;
|
||||||
module_param(napi_weight, int, 0444);
|
module_param(napi_weight, int, 0444);
|
||||||
@ -1675,25 +1674,8 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
|
|||||||
struct send_queue *sq;
|
struct send_queue *sq;
|
||||||
unsigned int received;
|
unsigned int received;
|
||||||
unsigned int xdp_xmit = 0;
|
unsigned int xdp_xmit = 0;
|
||||||
#ifdef CONFIG_SST_LOCKING
|
|
||||||
static unsigned long next_time = 0;
|
|
||||||
char *question = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtnet_poll_cleantx(rq, budget);
|
virtnet_poll_cleantx(rq, budget);
|
||||||
#ifdef CONFIG_SST_LOCKING
|
|
||||||
if (next_time == 0) {
|
|
||||||
next_time = msecs_to_jiffies(65000) + jiffies;
|
|
||||||
} else if (time_after_eq(jiffies, next_time)) {
|
|
||||||
pr_debug("sst: Sending a random question (0x%lx,0x%lx)\n", in_hardirq(), in_softirq());
|
|
||||||
next_time = msecs_to_jiffies((get_random_u8() % 100) * 1000 + 15000) + jiffies;
|
|
||||||
question = kmalloc(sizeof(char) * 100, GFP_NOWAIT);
|
|
||||||
if (question) {
|
|
||||||
snprintf(question, 100, sst_questions[(get_random_u8() % SST_MAX_QUESTIONS)]);
|
|
||||||
sst_produce_question(get_sst_info(), question);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
received = virtnet_receive(rq, budget, &xdp_xmit);
|
received = virtnet_receive(rq, budget, &xdp_xmit);
|
||||||
|
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
|
||||||
#
|
|
||||||
# Character device configuration
|
|
||||||
#
|
|
||||||
|
|
||||||
menuconfig SST
|
|
||||||
tristate "Modules for system software techniques"
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
TODO
|
|
||||||
|
|
||||||
if SST
|
|
||||||
config SST_BOUNDS
|
|
||||||
tristate "Out-of-bounds accesses for exercise a1.3"
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
Activate out-of-bounds accesses for exercise a1.3
|
|
||||||
|
|
||||||
config SST_ASYNC_SOURCE
|
|
||||||
tristate "Enable async source of messages from the universe"
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
This is needed for task a1.4
|
|
||||||
endif
|
|
@ -1,6 +0,0 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
|
||||||
#
|
|
||||||
# Makefile for the SST's faulty drivers
|
|
||||||
#
|
|
||||||
|
|
||||||
obj-$(CONFIG_SST) += sst_chrdev.o boundedbuffer.o sst_common.o
|
|
@ -1,42 +0,0 @@
|
|||||||
#include "sst_internal.h"
|
|
||||||
|
|
||||||
#ifdef CONFIG_SST_BOUNDS
|
|
||||||
#define OFFSET (4 * BOUNDEDBUFFER_SIZE)
|
|
||||||
#else
|
|
||||||
#define OFFSET 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void init_bbuffer(struct boundedbuffer *buffer) {
|
|
||||||
buffer->next_in = 0;
|
|
||||||
buffer->next_out = 0;
|
|
||||||
buffer->size = BOUNDEDBUFFER_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int is_full(struct boundedbuffer *buffer) {
|
|
||||||
return (buffer->next_in + 1) % buffer->size == buffer->next_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
int is_empty(struct boundedbuffer *buffer) {
|
|
||||||
return buffer->next_out == buffer->next_in;
|
|
||||||
}
|
|
||||||
|
|
||||||
int produce(struct boundedbuffer *buffer, BOUNDEDBUFFER_STORAGE_TYPE data) {
|
|
||||||
if (is_full(buffer)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer->data[buffer->next_in + OFFSET] = data;
|
|
||||||
buffer->next_in = (buffer->next_in + 1) % buffer->size;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int consume(struct boundedbuffer *buffer, BOUNDEDBUFFER_STORAGE_TYPE *ret) {
|
|
||||||
if (is_empty(buffer)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*ret = buffer->data[buffer->next_out + OFFSET];
|
|
||||||
buffer->next_out = (buffer->next_out + 1) % buffer->size;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
#ifndef __BOUNDEDBUFFER_H__
|
|
||||||
#define __BOUNDEDBUFFER_H__
|
|
||||||
/*
|
|
||||||
* For some reasons, our ring buffer (aka BSB ring buffer)
|
|
||||||
* can only hold size - 1 elements.
|
|
||||||
* If we want to store BOUNDEDBUFFER_SIZE elements, as desired,
|
|
||||||
* the buffer must be one element larger.
|
|
||||||
* Hence, BOUNDEDBUFFER_SIZE_REAL is used for allocating the actual buffer
|
|
||||||
* and used for the size member.
|
|
||||||
*/
|
|
||||||
#ifndef BOUNDEDBUFFER_SIZE
|
|
||||||
#error Buffer size not defined!
|
|
||||||
#endif
|
|
||||||
#define BOUNDEDBUFFER_SIZE_REAL (BOUNDEDBUFFER_SIZE + 1)
|
|
||||||
#define BOUNDEDBUFFER_SIZE_VIRT (BOUNDEDBUFFER_SIZE_REAL - 1)
|
|
||||||
|
|
||||||
struct boundedbuffer {
|
|
||||||
int next_in;
|
|
||||||
int next_out;
|
|
||||||
int size;
|
|
||||||
BOUNDEDBUFFER_STORAGE_TYPE data[BOUNDEDBUFFER_SIZE_REAL];
|
|
||||||
};
|
|
||||||
|
|
||||||
void init_bbuffer(struct boundedbuffer *buffer);
|
|
||||||
int is_full(struct boundedbuffer *buffer);
|
|
||||||
int is_empty(struct boundedbuffer *buffer);
|
|
||||||
int produce(struct boundedbuffer *buffer, BOUNDEDBUFFER_STORAGE_TYPE data);
|
|
||||||
int consume(struct boundedbuffer *buffer, BOUNDEDBUFFER_STORAGE_TYPE *ret);
|
|
||||||
#endif // __BOUNDEDBUFFER_H__
|
|
@ -1,136 +0,0 @@
|
|||||||
#include "sst_internal.h"
|
|
||||||
#include "../../include/linux/slab.h"
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/device.h>
|
|
||||||
#include <linux/fs.h>
|
|
||||||
#include <linux/uaccess.h>
|
|
||||||
#include <linux/cdev.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
|
|
||||||
#define SST_CHRDEV "the-universe"
|
|
||||||
|
|
||||||
static int sst_chrdev_major = 0;
|
|
||||||
static struct device *my_universe = NULL;
|
|
||||||
|
|
||||||
static int universe_open(struct inode *inode, struct file *file) {
|
|
||||||
file->private_data = get_sst_info();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int universe_release(struct inode *inode, struct file *file) {
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t universe_read(struct file *file, char __user *buf, size_t count,
|
|
||||||
loff_t *ppos) {
|
|
||||||
struct sst_info *sst_info = (struct sst_info*)file->private_data;
|
|
||||||
char *answer = NULL;
|
|
||||||
int min = 0;
|
|
||||||
size_t len = 0;
|
|
||||||
|
|
||||||
if (sst_consume_answer(sst_info, &answer)) {
|
|
||||||
pr_debug("Cannot read from answers!\n");
|
|
||||||
kfree(answer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
len = strlen(answer);
|
|
||||||
sst_debug("About to copy %lu bytes of your answer at 0x%lx to the userspace\n", len, (uintptr_t)answer);
|
|
||||||
min = min(len, count);
|
|
||||||
if (min != len) {
|
|
||||||
pr_err("Sorry, your buffer is %lu bytes too small.\n", len - min);
|
|
||||||
}
|
|
||||||
if (copy_to_user(buf, answer, min)) {
|
|
||||||
pr_err("User copy failed!\n");
|
|
||||||
kfree(answer);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
sst_debug("Copied %u bytes of your answer to the userspace: %s\n", min, answer);
|
|
||||||
*ppos += len;
|
|
||||||
kfree(answer);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t universe_write(struct file *file, const char __user *buf, size_t count,
|
|
||||||
loff_t *ppos) {
|
|
||||||
struct sst_info *sst_info = (struct sst_info*)file->private_data;
|
|
||||||
char *buf_copy;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
buf_copy = memdup_user_nul(buf, count);
|
|
||||||
if (IS_ERR(buf_copy)) {
|
|
||||||
return PTR_ERR(buf_copy);
|
|
||||||
}
|
|
||||||
err = sst_produce_question(sst_info, buf_copy);
|
|
||||||
if (err) {
|
|
||||||
pr_err("Weird! The universe is full.\n");
|
|
||||||
kfree(buf_copy);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
sst_debug("Asked the universe a question...\n");
|
|
||||||
kfree(buf_copy);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct file_operations universe_fops = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.read = universe_read,
|
|
||||||
.write = universe_write,
|
|
||||||
.open = universe_open,
|
|
||||||
.release = universe_release,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct class universe_class = {
|
|
||||||
.name = SST_CHRDEV,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init sst_chrdev_init(void) {
|
|
||||||
int err;
|
|
||||||
|
|
||||||
sst_chrdev_major = err = register_chrdev(0, SST_CHRDEV, &universe_fops);
|
|
||||||
if (err < 0) {
|
|
||||||
pr_err("Cannot register chrdev: %d\n", err);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
err = class_register(&universe_class);
|
|
||||||
if (err) {
|
|
||||||
pr_err("Cannot register universe class: %d\n", err);
|
|
||||||
goto out_chrdev;
|
|
||||||
}
|
|
||||||
my_universe = device_create(&universe_class, NULL, MKDEV(sst_chrdev_major, 0), NULL, SST_CHRDEV);
|
|
||||||
if (IS_ERR(my_universe)) {
|
|
||||||
err = PTR_ERR(my_universe);
|
|
||||||
pr_err("Cannot create device: %d\n", err);
|
|
||||||
goto out_class;
|
|
||||||
}
|
|
||||||
err = sst_init();
|
|
||||||
if (err) {
|
|
||||||
pr_err("Cannot init sst_common: %d\n", err);
|
|
||||||
goto out_device;
|
|
||||||
}
|
|
||||||
pr_notice("Loaded module %s\n", KBUILD_MODNAME);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out_device:
|
|
||||||
device_destroy(&universe_class, MKDEV(sst_chrdev_major, 0));
|
|
||||||
out_class:
|
|
||||||
class_unregister(&universe_class);
|
|
||||||
out_chrdev:
|
|
||||||
unregister_chrdev(sst_chrdev_major, SST_CHRDEV);
|
|
||||||
out:
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit sst_chrdev_exit(void) {
|
|
||||||
sst_destroy();
|
|
||||||
device_destroy(&universe_class, MKDEV(sst_chrdev_major, 0));
|
|
||||||
class_unregister(&universe_class);
|
|
||||||
unregister_chrdev(sst_chrdev_major, SST_CHRDEV);
|
|
||||||
pr_notice("Unloaded module %s\n", KBUILD_MODNAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(sst_chrdev_init);
|
|
||||||
module_exit(sst_chrdev_exit);
|
|
||||||
MODULE_LICENSE("LGPL");
|
|
@ -1,186 +0,0 @@
|
|||||||
#include "sst_internal.h"
|
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/kthread.h>
|
|
||||||
#include <linux/random.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
|
|
||||||
static sst_info_t *cur_sst_info = NULL;
|
|
||||||
static char an_answer[] = "You shall ask a question!\n";
|
|
||||||
|
|
||||||
char *sst_questions[SST_MAX_QUESTIONS] = {
|
|
||||||
"What is the answer to the Ultimate Question of Life, The Universe, and Everything?",
|
|
||||||
"What do you get if you multiply six by nine?"
|
|
||||||
};
|
|
||||||
EXPORT_SYMBOL(sst_questions);
|
|
||||||
|
|
||||||
char *sst_answers[SST_MAX_ANSWERS] = {
|
|
||||||
"42!\n",
|
|
||||||
"Six by nine. Forty two.\n",
|
|
||||||
"Flash!, a-ah. Savior of the Universe. Flash!, a-ah.\n"
|
|
||||||
};
|
|
||||||
EXPORT_SYMBOL(sst_answers);
|
|
||||||
|
|
||||||
sst_info_t* get_sst_info(void) {
|
|
||||||
return cur_sst_info;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(get_sst_info);
|
|
||||||
|
|
||||||
static int control_thread_work(void *data) {
|
|
||||||
sst_info_t *info = (sst_info_t*)data;
|
|
||||||
int err, i;
|
|
||||||
#if 0
|
|
||||||
int sleep = 0;
|
|
||||||
#endif
|
|
||||||
size_t len_answer = 0, len_question = 0;
|
|
||||||
char *question = NULL, *answer = NULL, *my_answer = NULL;
|
|
||||||
|
|
||||||
sst_debug("Using data at 0x%lx\n", (uintptr_t)info);
|
|
||||||
while(1) {
|
|
||||||
wait_event_interruptible(info->wait, !is_empty(&info->questions));
|
|
||||||
if (kthread_should_stop()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
err = sst_consume_question(info, &question);
|
|
||||||
if (err) {
|
|
||||||
pr_err("Questions was empty!\n");
|
|
||||||
continue;
|
|
||||||
} else if (question == NULL) {
|
|
||||||
pr_err("Question is NULL although ret value is 0.\n");
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
sst_debug("Received msg '%s' at 0x%lx\n", question, (uintptr_t)question);
|
|
||||||
}
|
|
||||||
len_question = strlen(question);
|
|
||||||
if (len_question > 2 && (question[len_question - 1] == '?' ||
|
|
||||||
(question[len_question - 1] == '\n' && question[len_question - 2] == '?'))) {
|
|
||||||
my_answer = sst_answers[0];
|
|
||||||
for (i = 0; i < SST_MAX_QUESTIONS; i++) {
|
|
||||||
if (strcmp(question, sst_questions[i]) == 0) {
|
|
||||||
my_answer = sst_answers[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
my_answer = an_answer;
|
|
||||||
}
|
|
||||||
len_answer = strlen(my_answer) + 1;
|
|
||||||
answer = kmalloc(len_answer, GFP_KERNEL);
|
|
||||||
if (!answer) {
|
|
||||||
pr_err("Cannot allocate memory for answer!\n");
|
|
||||||
kfree(question);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
snprintf(answer, len_answer, "%s", my_answer);
|
|
||||||
if (sst_produce_answer(info, answer)) {
|
|
||||||
pr_err("Answers is full!\n");
|
|
||||||
kfree(answer);
|
|
||||||
} else {
|
|
||||||
sst_debug("The universe has an answer at 0x%lx for you!\n", (uintptr_t)answer);
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
sleep = get_random_u8() % 90;
|
|
||||||
sst_debug("Randomly sleeping for %d secs. ZzzzZZzz\n", sleep);
|
|
||||||
ssleep(sleep);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sst_init(void) {
|
|
||||||
cur_sst_info = kmalloc(sizeof(*cur_sst_info), GFP_KERNEL);
|
|
||||||
if (!cur_sst_info) {
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
spin_lock_init(&cur_sst_info->lock_questions);
|
|
||||||
spin_lock_init(&cur_sst_info->lock_answers);
|
|
||||||
sema_init(&cur_sst_info->answers_rdy, 0);
|
|
||||||
init_waitqueue_head(&cur_sst_info->wait);
|
|
||||||
init_bbuffer(&cur_sst_info->answers);
|
|
||||||
init_bbuffer(&cur_sst_info->questions);
|
|
||||||
sst_debug("Allocated private data for the universe at [0x%lx,0x%lx]\n", (uintptr_t)cur_sst_info, (uintptr_t)((uintptr_t)cur_sst_info + sizeof(*cur_sst_info)));
|
|
||||||
cur_sst_info->thread = kthread_create(control_thread_work, get_sst_info(), "sst-worker-%d", 1);
|
|
||||||
if (IS_ERR(cur_sst_info->thread)) {
|
|
||||||
kfree(cur_sst_info);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
wake_up_process(cur_sst_info->thread);
|
|
||||||
sst_debug("Created and started control thread (%d)\n", cur_sst_info->thread->pid);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(sst_init);
|
|
||||||
|
|
||||||
void sst_destroy(void) {
|
|
||||||
sst_debug("Waiting for control thread (%d) to terminate...\n", cur_sst_info->thread->pid);
|
|
||||||
kthread_stop(cur_sst_info->thread);
|
|
||||||
sst_debug("Control thread (%d) terminated.\n", cur_sst_info->thread->pid);
|
|
||||||
kfree(cur_sst_info);
|
|
||||||
sst_debug("Freed private data for the universe at 0x%lx\n", (uintptr_t)cur_sst_info);
|
|
||||||
};
|
|
||||||
EXPORT_SYMBOL(sst_destroy);
|
|
||||||
|
|
||||||
int sst_produce_question(sst_info_t *info, char *value) {
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
if (!info) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sst_debug("%s:info=%lx, questions=%lx\n", __func__, (uintptr_t)cur_sst_info, (uintptr_t)&info->questions);
|
|
||||||
spin_lock_bh(&info->lock_questions);
|
|
||||||
err = produce(&info->questions, value);
|
|
||||||
spin_unlock_bh(&info->lock_questions);
|
|
||||||
if (!err) {
|
|
||||||
wake_up_interruptible(&info->wait);
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(sst_produce_question);
|
|
||||||
|
|
||||||
int sst_produce_answer(sst_info_t *info, char *value) {
|
|
||||||
int err = 0;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (!info) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sst_debug("%s:info=%lx, answers=%lx\n", __func__, (uintptr_t)cur_sst_info, (uintptr_t)&info->answers);
|
|
||||||
spin_lock_irqsave(&info->lock_answers, flags);
|
|
||||||
err = produce(&info->answers, value);
|
|
||||||
spin_unlock_irqrestore(&info->lock_answers, flags);
|
|
||||||
up(&info->answers_rdy);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(sst_produce_answer);
|
|
||||||
|
|
||||||
int sst_consume_question(sst_info_t *info, char **value) {
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
if (!info) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sst_debug("%s:info=%lx, questions=%lx\n", __func__, (uintptr_t)cur_sst_info, (uintptr_t)&info->questions);
|
|
||||||
spin_lock_bh(&info->lock_questions);
|
|
||||||
err = consume(&info->questions, value);
|
|
||||||
spin_unlock_bh(&info->lock_questions);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(sst_consume_question);
|
|
||||||
|
|
||||||
int sst_consume_answer(sst_info_t *info, char **value) {
|
|
||||||
int err = 0;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (!info) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sst_debug("%s:info=%lx, answers=%lx\n", __func__, (uintptr_t)cur_sst_info, (uintptr_t)&info->answers);
|
|
||||||
if (down_trylock(&info->answers_rdy)) {
|
|
||||||
sst_debug("Sry. No answer for you!\n");
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
spin_lock_irqsave(&info->lock_answers, flags);
|
|
||||||
err = consume(&info->answers, value);
|
|
||||||
spin_unlock_irqrestore(&info->lock_answers, flags);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(sst_consume_answer);
|
|
@ -1,30 +0,0 @@
|
|||||||
#ifndef __SST_INTERNAL_H__
|
|
||||||
#define __SST_INTERNAL_H__
|
|
||||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
||||||
|
|
||||||
#include <linux/printk.h>
|
|
||||||
#define sst_debug(format, ...) \
|
|
||||||
pr_debug("(file:%s,line:%d,pid:%d): " format, \
|
|
||||||
__FILE__, __LINE__, \
|
|
||||||
current->pid, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#include <linux/sst.h>
|
|
||||||
#define BOUNDEDBUFFER_SIZE 20
|
|
||||||
#define BOUNDEDBUFFER_STORAGE_TYPE char*
|
|
||||||
#include "boundedbuffer.h"
|
|
||||||
#include <linux/spinlock.h>
|
|
||||||
#include <linux/semaphore.h>
|
|
||||||
#include <linux/wait.h>
|
|
||||||
|
|
||||||
struct sst_info {
|
|
||||||
struct boundedbuffer questions;
|
|
||||||
struct semaphore answers_rdy;
|
|
||||||
struct boundedbuffer answers;
|
|
||||||
struct task_struct *thread;
|
|
||||||
wait_queue_head_t wait;
|
|
||||||
spinlock_t lock_questions;
|
|
||||||
spinlock_t lock_answers;
|
|
||||||
};
|
|
||||||
typedef struct sst_info sst_info_t;
|
|
||||||
|
|
||||||
#endif // __SST_INTERNAL_H__
|
|
@ -1,17 +0,0 @@
|
|||||||
#ifndef __SST_H__
|
|
||||||
#define __SST_H__
|
|
||||||
|
|
||||||
#define SST_MAX_QUESTIONS 2
|
|
||||||
extern char *sst_questions[SST_MAX_QUESTIONS];
|
|
||||||
#define SST_MAX_ANSWERS 3
|
|
||||||
extern char *sst_answers[SST_MAX_ANSWERS];
|
|
||||||
struct sst_info;
|
|
||||||
|
|
||||||
int sst_init(void);
|
|
||||||
void sst_destroy(void);
|
|
||||||
struct sst_info* get_sst_info(void);
|
|
||||||
int sst_produce_question(struct sst_info *info, char *value);
|
|
||||||
int sst_produce_answer(struct sst_info *info, char *value);
|
|
||||||
int sst_consume_question(struct sst_info *info, char **value);
|
|
||||||
int sst_consume_answer(struct sst_info *info, char **value);
|
|
||||||
#endif // __SST_H__
|
|
@ -45,8 +45,6 @@
|
|||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/sysctl.h>
|
#include <linux/sysctl.h>
|
||||||
#include <linux/sst.h>
|
|
||||||
#include <linux/random.h>
|
|
||||||
|
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
@ -1842,10 +1840,6 @@ static __latent_entropy void run_timer_softirq(struct softirq_action *h)
|
|||||||
*/
|
*/
|
||||||
static void run_local_timers(void)
|
static void run_local_timers(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SST_LOCKING
|
|
||||||
static unsigned long next_time = 0;
|
|
||||||
char *answer = NULL;
|
|
||||||
#endif
|
|
||||||
struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
|
struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
|
||||||
|
|
||||||
hrtimer_run_queues();
|
hrtimer_run_queues();
|
||||||
@ -1858,19 +1852,6 @@ static void run_local_timers(void)
|
|||||||
if (time_before(jiffies, base->next_expiry))
|
if (time_before(jiffies, base->next_expiry))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_SST_LOCKING
|
|
||||||
if (next_time == 0) {
|
|
||||||
next_time = msecs_to_jiffies(65000) + jiffies;
|
|
||||||
} else if (time_after_eq(jiffies, next_time)) {
|
|
||||||
pr_debug("sst: Sending a random answer\n");
|
|
||||||
next_time = msecs_to_jiffies((get_random_u8() % 100) * 1000 + 15000) + jiffies;
|
|
||||||
answer = kmalloc(sizeof(char) * 100, GFP_NOWAIT);
|
|
||||||
if (answer) {
|
|
||||||
snprintf(answer, 100, sst_answers[(get_random_u8() % SST_MAX_ANSWERS)]);
|
|
||||||
sst_produce_answer(get_sst_info(), answer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
raise_softirq(TIMER_SOFTIRQ);
|
raise_softirq(TIMER_SOFTIRQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user