Skip to content
Merged
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
197 changes: 184 additions & 13 deletions kernel/exceptions/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@

static uint64_t _msecs;

static int64_t g_wall_offset_us = 0;
static int g_sync = 0;

static int32_t g_tz_offset_min = 0;

static inline uint64_t rd_cntfrq_el0(void) {
uint64_t v;
asm volatile ("mrs %0, cntfrq_el0" : "=r"(v));
return v;
}

void timer_reset() {
uint64_t freq;
asm volatile ("mrs %0, cntfrq_el0" : "=r"(freq));
uint64_t interval = (freq * _msecs)/1000;
uint64_t freq = rd_cntfrq_el0();
uint64_t interval = (freq * _msecs) / 1000;
asm volatile ("msr cntp_tval_el0, %0" :: "r"(interval));
}

void timer_enable() {
static inline void timer_enable() {
Comment thread
CodeAnarchist marked this conversation as resolved.
uint64_t val = 1;
asm volatile ("msr cntp_ctl_el0, %0" :: "r"(val));
asm volatile ("msr cntkctl_el1, %0" :: "r"(val));
Expand All @@ -27,9 +37,8 @@ void timer_init(uint64_t msecs) {
}

void virtual_timer_reset(uint64_t smsecs) {
uint64_t freq;
asm volatile ("mrs %0, cntfrq_el0" : "=r"(freq));
uint64_t interval = (freq * smsecs)/1000;
uint64_t freq = rd_cntfrq_el0();
uint64_t interval = (freq * smsecs) / 1000;
asm volatile ("msr cntv_tval_el0, %0" :: "r"(interval));
}

Expand All @@ -40,9 +49,8 @@ void virtual_timer_enable() {

uint64_t virtual_timer_remaining_msec() {
uint64_t ticks;
uint64_t freq;
uint64_t freq = rd_cntfrq_el0();
asm volatile ("mrs %0, cntv_tval_el0" : "=r"(ticks));
asm volatile ("mrs %0, cntfrq_el0" : "=r"(freq));
return (ticks * 1000) / freq;
}

Expand All @@ -53,8 +61,171 @@ uint64_t timer_now() {
}

uint64_t timer_now_msec() {
uint64_t ticks, freq;
asm volatile ("mrs %0, cntvct_el0" : "=r"(ticks));
asm volatile ("mrs %0, cntfrq_el0" : "=r"(freq));
uint64_t ticks = timer_now();
uint64_t freq = rd_cntfrq_el0();
return (ticks * 1000) / freq;
}
}

uint64_t timer_now_usec(void) {
uint64_t ticks = timer_now();
uint64_t freq = rd_cntfrq_el0();

uint64_t q = ticks / freq;
uint64_t r = ticks % freq;

uint64_t us = q * 1000000ULL;
us += (r * 1000000ULL) / freq;
return us;
}

void timer_apply_sntp_sample_us(uint64_t server_unix_us) {
int64_t mono_us = (int64_t)timer_now_usec();
int64_t off = (int64_t)server_unix_us - mono_us;

g_wall_offset_us = off;
g_sync = 1;
}

int timer_is_synchronised(void) {
return g_sync;
}

uint64_t timer_unix_time_ms(void) {
if (!g_sync) return 0;
uint64_t now_us = timer_now_usec();
int64_t off = g_wall_offset_us;

int64_t unix_us = (int64_t)now_us + off;
if (unix_us < 0) return 0;
return (uint64_t)unix_us / 1000ULL;
}

void timer_set_timezone_minutes(int32_t minutes){
g_tz_offset_min = minutes;
}

int32_t timer_get_timezone_minutes(void){
return g_tz_offset_min;
}

uint64_t timer_local_time_ms(void){
uint64_t utc_ms = timer_unix_time_ms();
if (utc_ms == 0) return 0;
int64_t adj = (int64_t)utc_ms + (int64_t)g_tz_offset_min * 60LL * 1000LL;
if (adj < 0) return 0;
return (uint64_t)adj;
}

int timer_set_manual_unix_time_ms(uint64_t unix_ms){
if (g_sync) return -1;
uint64_t now_us = timer_now_usec();
int64_t off = (int64_t)(unix_ms * 1000ULL) - (int64_t)now_us;
g_wall_offset_us = off;
return 0;
}

static int64_t days_from_civil(int64_t y, unsigned m, unsigned d){
y -= (m <= 2);
const int64_t era = (y >= 0 ? y : y - 399) / 400;
const unsigned yoe = (unsigned)(y - era * 400);
const unsigned doy = (153*(m + (m > 2 ? -3 : 9)) + 2)/5 + d - 1;
const unsigned doe = yoe * 365 + yoe/4 - yoe/100 + yoe/400 + doy;
return era * 146097 + (int64_t)doe - 719468;
}

static void civil_from_days(int64_t z, int64_t* y, unsigned* m, unsigned* d){
z += 719468;
const int64_t era = (z >= 0 ? z : z - 146096) / 146097;
const unsigned doe = (unsigned)(z - era * 146097);
const unsigned yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365;
int64_t y_full = (int64_t)yoe + era * 400;
const unsigned doy = doe - (365*yoe + yoe/4 - yoe/100 + yoe/400);
const unsigned mp = (5*doy + 2)/153;
const unsigned dd = doy - (153*mp + 2)/5 + 1;
const unsigned mm = mp + (mp < 10 ? 3 : -9);
y_full += (mm <= 2);
*y = y_full; *m = mm; *d = dd;
}

static void fmt2u(uint64_t v, char out[3]){ //maybe move this in a helper file
out[0] = (char)('0' + (v/10u)%10u);
out[1] = (char)('0' + (v%10u));
out[2] = '\0';
}

void timer_unix_ms_to_datetime(uint64_t unix_ms, int use_local, DateTime* out){
if (!out) return;
int64_t ms = (int64_t)unix_ms;
if (use_local) ms += (int64_t)g_tz_offset_min * 60LL * 1000LL;
if (ms < 0) ms = 0;

uint64_t sec = (uint64_t)ms / 1000ULL;
uint64_t sod = sec % 86400ULL;
uint64_t days= sec / 86400ULL;

int64_t Y;
unsigned M,D;
civil_from_days((int64_t)days, &Y, &M, &D);

out->year = (uint16_t)Y;
out->month = (uint8_t)M;
out->day = (uint8_t)D;
out->hour = (uint8_t)(sod / 3600ULL);
out->minute = (uint8_t)((sod % 3600ULL) / 60ULL);
out->second = (uint8_t)(sod % 60ULL);
}

uint64_t timer_datetime_to_unix_ms(const DateTime* dt, int is_local){
if (!dt) return 0;
uint16_t Y = dt->year;
if (Y < 1970) Y = 1970;
unsigned M = (dt->month >= 1 && dt->month <= 12) ? dt->month : 1;
unsigned D = (dt->day >= 1 && dt->day <= 31) ? dt->day : 1;
unsigned h = (dt->hour <= 23) ? dt->hour : 0;
unsigned m = (dt->minute <= 59) ? dt->minute : 0;
unsigned s = (dt->second <= 59) ? dt->second : 0;

int64_t days = days_from_civil((int64_t)Y, M, D);
uint64_t sec = (uint64_t)(days >= 0 ? days : 0) * 86400ULL + (uint64_t)h*3600ULL + (uint64_t)m*60ULL + (uint64_t)s;

int64_t ms = (int64_t)sec * 1000LL;
if (is_local) ms -= (int64_t)g_tz_offset_min * 60LL * 1000LL;
if (ms < 0) ms = 0;
return (uint64_t)ms;
}

int timer_now_datetime(DateTime* out, int use_local){
if (!out) return 0;
uint64_t ms = use_local ? timer_local_time_ms() : timer_unix_time_ms();
if (ms == 0) return 0;
timer_unix_ms_to_datetime(ms, 0, out);
return 1;
}

void timer_datetime_to_string(const DateTime* dt, char* buf, uint32_t buflen){
if (!dt || !buf || buflen < 20) return;
uint16_t Y = dt->year;
buf[0] = (char)('0' + (Y/1000)%10);
buf[1] = (char)('0' + (Y/100)%10);
buf[2] = (char)('0' + (Y/10)%10);
buf[3] = (char)('0' + (Y%10));
buf[4] = '-';

char mm[3], dd[3], HH[3], MM[3], SS[3];
fmt2u(dt->month, mm);
fmt2u(dt->day, dd);
fmt2u(dt->hour, HH);
fmt2u(dt->minute, MM);
fmt2u(dt->second, SS);

buf[5] = mm[0]; buf[6] = mm[1];
buf[7] = '-';
buf[8] = dd[0]; buf[9] = dd[1];
buf[10] = ' ';
buf[11] = HH[0]; buf[12] = HH[1];
buf[13] = ':';
buf[14] = MM[0]; buf[15] = MM[1];
buf[16] = ':';
buf[17] = SS[0]; buf[18] = SS[1];
buf[19] = '\0';
}
35 changes: 34 additions & 1 deletion kernel/exceptions/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

#include "types.h"

#ifdef __cplusplus
extern "C" {
#endif

void timer_init(uint64_t msecs);
void timer_reset();

Expand All @@ -11,5 +15,34 @@ uint64_t virtual_timer_remaining_msec();

uint64_t timer_now();
uint64_t timer_now_msec();
uint64_t timer_now_usec(void);

void timer_apply_sntp_sample_us(uint64_t server_unix_us);
int timer_is_synchronised(void);
uint64_t timer_unix_time_ms(void);

void timer_set_timezone_minutes(int32_t minutes);
int32_t timer_get_timezone_minutes(void);

uint64_t timer_local_time_ms(void);
int timer_set_manual_unix_time_ms(uint64_t unix_ms);

typedef struct {
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
} DateTime;

void timer_unix_ms_to_datetime(uint64_t unix_ms, int use_local, DateTime* out);
uint64_t timer_datetime_to_unix_ms(const DateTime* dt, int is_local);
int timer_now_datetime(DateTime* out, int use_local);
void timer_datetime_to_string(const DateTime* dt, char* buf, uint32_t buflen);

void permanent_disable_timer();

void permanent_disable_timer();
#ifdef __cplusplus
}
#endif
2 changes: 1 addition & 1 deletion kernel/networking/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ int net_rx_frame(sizedptr *out_frame) {
}

const net_l2l3_endpoint* network_get_local_endpoint() {
static net_l2l3_endpoint dummy = {0};
static net_l2l3_endpoint dummy = {};
return dispatch ? &dispatch->get_local_ep() : &dummy;
}

Expand Down
18 changes: 2 additions & 16 deletions kernel/networking/network_dispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ bool NetworkDispatch::enqueue_frame(const sizedptr &frame)

int NetworkDispatch::net_task()
{
network_net_set_pid(get_current_proc_pid());
for (;;) {
bool did_work = false;
sizedptr pkt;
sizedptr pkt{0,0};

if (!rx_queue.is_empty() && rx_queue.dequeue(pkt)) {
did_work = true;
Expand Down Expand Up @@ -126,21 +127,6 @@ bool NetworkDispatch::dequeue_packet_for(uint16_t pid, sizedptr *out)
return true;
}

static sizedptr make_user_copy(const sizedptr &src)
{
sizedptr out{0, 0};
uintptr_t mem = malloc(src.size);
if (!mem) return out;

memcpy(reinterpret_cast<void*>(mem),
reinterpret_cast<const void*>(src.ptr),
src.size);

out.ptr = mem;
out.size = src.size;
return out;
}

sizedptr NetworkDispatch::make_copy(const sizedptr &in)
{
sizedptr out{0, 0};
Expand Down
27 changes: 20 additions & 7 deletions kernel/networking/port_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@
#include "types.h"
#include "networking/port_manager.h"
#include "net/internet_layer/ipv4.h"
#include "math/rng.h"

static port_entry_t g_port_table[PROTO_COUNT][MAX_PORTS];//tab proto/port

static inline bool port_valid(uint16_t p) {
static inline bool port_valid(uint32_t p) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing p parameter to uint32_t doesn't add any value here if all of the arguments ever passed to it are converted/truncated to 16-bits. If every value passed to this function is already between 0 and MAX_PORTS then at worst it wastes some CPU cycles for nothing and at best it gets optimized-out.

I removed it again in the update compiler warnings clean up branch. It was disused in the network changes which landed in master branch anyway, so kind of moot.

return p > 0 && p < MAX_PORTS;
}

static inline bool proto_valid(protocol_t proto) {
return (uint32_t)proto< PROTO_COUNT;
return (uint32_t)proto < PROTO_COUNT;
}

void port_manager_init() {
for (int pr = 0; pr < PROTO_COUNT; ++pr) {
void port_manager_init(void) {
for (uint32_t pr = 0; pr < PROTO_COUNT; ++pr) {
for (uint32_t p = 0; p < MAX_PORTS; ++p) {
g_port_table[pr][p].used = false;
g_port_table[pr][p].pid = PORT_FREE_OWNER;
Expand All @@ -27,7 +29,18 @@ int port_alloc_ephemeral(protocol_t proto,
port_recv_handler_t handler)
{
if (!proto_valid(proto)) return -1;
for (uint16_t p = PORT_MIN_EPHEMERAL; p <= PORT_MAX_EPHEMERAL; ++p) {

rng_t rng;
rng_init_random(&rng);
uint32_t seed = rng_next32(&rng);

uint32_t minp = (uint32_t)PORT_MIN_EPHEMERAL;
uint32_t maxp = (uint32_t)PORT_MAX_EPHEMERAL;
uint32_t range = maxp - minp + 1u;
uint32_t first = minp + (seed % range);

for (uint32_t i = 0; i < range; ++i) {
uint32_t p = minp + ((first - minp + i) % range);
port_entry_t *e = &g_port_table[proto][p];
if (!e->used) {
e->used = true;
Expand Down Expand Up @@ -67,8 +80,8 @@ bool port_unbind(protocol_t proto,
}

void port_unbind_all(uint16_t pid) {
for (int pr = 0; pr < PROTO_COUNT; ++pr) {
for (uint16_t p = 1; p < MAX_PORTS; ++p) {
for (uint32_t pr = 0; pr < PROTO_COUNT; ++pr) {
for (uint32_t p = 1; p < MAX_PORTS; ++p) {
port_entry_t *e = &g_port_table[pr][p];
if (e->used && e->pid == pid) {
e->used = false;
Expand Down
Loading