Skip to content

Commit ce6d6ca

Browse files
authored
Merge pull request #20 from Poprdi/kernel
Kernel
2 parents 83447c5 + 1ea4fdc commit ce6d6ca

71 files changed

Lines changed: 7138 additions & 272 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ members = [
1919
"compd",
2020
"init",
2121
"shelld",
22+
"settings",
2223
"tests/syscall-e2e",
24+
"tests/netcheck",
2325
"tests/spinning-cube",
2426
"tests/system-visualizer",
2527
]

bootloader/src/baremetal.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
use core::sync::atomic::{AtomicBool, Ordering};
77
use morpheus_display::console::TextConsole;
88

9+
use crate::baremetal_ops::network;
10+
911
// TYPES THAT CROSS THE BORDER
1012

1113
/// Raw framebuffer info from GOP. stride is pixels_per_scan_line from GOP.
@@ -287,6 +289,13 @@ pub unsafe fn enter_baremetal(config: BaremetalEntryConfig) -> ! {
287289
}
288290
};
289291

292+
// userspace network activation hook. we stay offline by default.
293+
network::init_userspace_network_activation(morpheus_network::dma::DmaRegion::new(
294+
platform.dma().cpu_base(),
295+
platform.dma().bus_base(),
296+
platform.dma().size(),
297+
), platform.tsc_freq());
298+
290299
// persistent storage — try to mount a real block device
291300
crate::storage::init_persistent_storage(platform.dma(), platform.tsc_freq());
292301

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod network;
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
use morpheus_network::boot::{probe_and_create_driver, ProbeError, ProbeResult};
2+
use morpheus_network::device::UnifiedNetDevice;
3+
use morpheus_network::stack::{NetConfig, NetInterface};
4+
5+
use super::{config, nic, state, tcp, udp_dns};
6+
7+
unsafe fn activate_network_from_userspace() -> i64 {
8+
morpheus_hwinit::serial::log_info("NET", 940, "userspace activation requested");
9+
10+
if state::has_driver() {
11+
morpheus_hwinit::serial::log_info("NET", 941, "already active");
12+
return 1;
13+
}
14+
15+
let Some((dma, tsc_freq)) = state::activation_context() else {
16+
morpheus_hwinit::serial::log_error("NET", 942, "activation failed: dma unavailable");
17+
return -1;
18+
};
19+
20+
morpheus_hwinit::serial::log_info("NET", 943, "probing NIC via network::probe_and_create_driver");
21+
let driver = match probe_and_create_driver(dma, tsc_freq) {
22+
Ok(ProbeResult::VirtIO(v)) => {
23+
morpheus_hwinit::serial::log_info("NET", 949, "probe selected virtio NIC");
24+
UnifiedNetDevice::VirtIO(v)
25+
}
26+
Ok(ProbeResult::Intel(i)) => {
27+
morpheus_hwinit::serial::log_info("NET", 951, "probe selected intel NIC");
28+
UnifiedNetDevice::Intel(i)
29+
}
30+
Err(ProbeError::NoDevice) => {
31+
morpheus_hwinit::serial::log_error("NET", 944, "probe failed: no supported NIC detected");
32+
nic::log_pci_network_candidates();
33+
return -2;
34+
}
35+
Err(ProbeError::VirtioInitFailed) => {
36+
morpheus_hwinit::serial::log_error("NET", 950, "virtio init failed");
37+
return -3;
38+
}
39+
Err(ProbeError::IntelInitFailed) => {
40+
morpheus_hwinit::serial::log_error("NET", 952, "intel init failed");
41+
return -3;
42+
}
43+
Err(ProbeError::DeviceNotResponding) => {
44+
morpheus_hwinit::serial::log_error("NET", 955, "nic mmio not responding");
45+
return -4;
46+
}
47+
Err(ProbeError::BarMappingFailed) => {
48+
morpheus_hwinit::serial::log_error("NET", 956, "nic bar mapping failure");
49+
return -5;
50+
}
51+
};
52+
53+
morpheus_hwinit::serial::log_ok("NET", 945, "driver initialized");
54+
55+
let stack = NetInterface::new(driver, NetConfig::dhcp());
56+
state::clear_net_handle_tables();
57+
state::set_stack(stack);
58+
59+
morpheus_hwinit::serial::log_info("NET", 946, "registering NIC ops");
60+
morpheus_hwinit::register_nic(morpheus_hwinit::NicOps {
61+
tx: Some(nic::user_net_tx),
62+
rx: Some(nic::user_net_rx),
63+
link_up: Some(nic::user_net_link_up),
64+
mac: Some(nic::user_net_mac),
65+
refill: Some(nic::user_net_refill),
66+
ctrl: Some(nic::user_net_ctrl),
67+
});
68+
69+
morpheus_hwinit::serial::log_info("NET", 957, "registering net stack ops");
70+
morpheus_hwinit::register_net_stack(morpheus_hwinit::NetStackOps {
71+
tcp_socket: Some(tcp::net_tcp_socket_impl),
72+
tcp_connect: Some(tcp::net_tcp_connect_impl),
73+
tcp_send: Some(tcp::net_tcp_send_impl),
74+
tcp_recv: Some(tcp::net_tcp_recv_impl),
75+
tcp_close: Some(tcp::net_tcp_close_impl),
76+
tcp_state: Some(tcp::net_tcp_state_impl),
77+
tcp_listen: Some(tcp::net_tcp_listen_impl),
78+
tcp_accept: Some(tcp::net_tcp_accept_impl),
79+
tcp_shutdown: Some(tcp::net_tcp_shutdown_impl),
80+
tcp_nodelay: Some(tcp::net_tcp_nodelay_impl),
81+
tcp_keepalive: Some(tcp::net_tcp_keepalive_impl),
82+
udp_socket: Some(udp_dns::net_udp_socket_impl),
83+
udp_send_to: Some(udp_dns::net_udp_send_to_impl),
84+
udp_recv_from: Some(udp_dns::net_udp_recv_from_impl),
85+
udp_close: Some(udp_dns::net_udp_close_impl),
86+
dns_start: Some(udp_dns::net_dns_start_impl),
87+
dns_result: Some(udp_dns::net_dns_result_impl),
88+
dns_set_servers: Some(udp_dns::net_dns_set_servers_impl),
89+
cfg_get: Some(config::net_cfg_get),
90+
cfg_dhcp: Some(config::net_cfg_dhcp),
91+
cfg_static_ip: Some(config::net_cfg_static_ip),
92+
cfg_hostname: Some(config::net_cfg_hostname),
93+
poll_drive: Some(config::net_poll_drive),
94+
poll_stats: Some(config::net_poll_stats),
95+
});
96+
97+
let _ = nic::user_net_refill();
98+
99+
let link_now = nic::user_net_link_up();
100+
if link_now != 0 {
101+
morpheus_hwinit::serial::log_ok("NET", 947, "activation complete: link up");
102+
} else {
103+
morpheus_hwinit::serial::log_info("NET", 948, "activation complete: link down");
104+
}
105+
106+
0
107+
}
108+
109+
pub(super) unsafe fn init_userspace_network_activation(
110+
dma: morpheus_network::dma::DmaRegion,
111+
tsc_freq: u64,
112+
) {
113+
state::set_activation_context(dma, tsc_freq);
114+
morpheus_hwinit::register_net_activation(activate_network_from_userspace);
115+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use morpheus_network::stack::NetState;
2+
3+
use super::state;
4+
5+
pub(super) unsafe fn net_cfg_get(buf: *mut u8) -> i64 {
6+
let Some(stack) = state::user_net_stack_mut() else {
7+
return -1;
8+
};
9+
10+
let out = &mut *(buf as *mut morpheus_hwinit::NetConfigInfo);
11+
core::ptr::write_bytes(
12+
out as *mut _ as *mut u8,
13+
0,
14+
core::mem::size_of::<morpheus_hwinit::NetConfigInfo>(),
15+
);
16+
17+
out.state = match stack.state() {
18+
NetState::Unconfigured => 0,
19+
NetState::DhcpDiscovering => 1,
20+
NetState::Ready => 2,
21+
NetState::Error => 3,
22+
};
23+
24+
out.flags |= 1;
25+
26+
if let Some(ip) = stack.ipv4_addr() {
27+
out.ipv4_addr = u32::from_be_bytes(ip.octets());
28+
out.prefix_len = 24;
29+
}
30+
if let Some(gw) = stack.gateway() {
31+
out.gateway = u32::from_be_bytes(gw.octets());
32+
out.flags |= 1 << 1;
33+
}
34+
if let Some(dns) = stack.dns() {
35+
out.dns_primary = u32::from_be_bytes(dns.octets());
36+
out.flags |= 1 << 2;
37+
}
38+
39+
let mac = stack.mac_address();
40+
out.mac[..6].copy_from_slice(&mac);
41+
out.mtu = 1500;
42+
state::write_hostname_to(out);
43+
44+
0
45+
}
46+
47+
pub(super) unsafe fn net_cfg_dhcp() -> i64 {
48+
let Some(stack) = state::user_net_stack_mut() else {
49+
return -1;
50+
};
51+
52+
match stack.restart_dhcp() {
53+
Ok(()) => 0,
54+
Err(_) => -1,
55+
}
56+
}
57+
58+
pub(super) unsafe fn net_cfg_static_ip(_ip: u32, _prefix_len: u8, _gateway: u32) -> i64 {
59+
-1
60+
}
61+
62+
pub(super) unsafe fn net_cfg_hostname(name: *const u8, len: usize) -> i64 {
63+
state::set_hostname(name, len)
64+
}
65+
66+
pub(super) unsafe fn net_poll_drive(timestamp_ms: u64) -> i64 {
67+
let Some(stack) = state::user_net_stack_mut() else {
68+
return -1;
69+
};
70+
71+
stack.device_mut().refill_rx_queue();
72+
let activity = stack.poll(timestamp_ms);
73+
stack.device_mut().collect_tx_completions();
74+
if activity { 1 } else { 0 }
75+
}
76+
77+
pub(super) unsafe fn net_poll_stats(buf: *mut u8) -> i64 {
78+
if state::user_net_stack_mut().is_none() {
79+
return -1;
80+
}
81+
let out = &mut *(buf as *mut morpheus_hwinit::NetStats);
82+
core::ptr::write_bytes(
83+
out as *mut _ as *mut u8,
84+
0,
85+
core::mem::size_of::<morpheus_hwinit::NetStats>(),
86+
);
87+
out.tx_packets = morpheus_network::stack::tx_packet_count() as u64;
88+
out.rx_packets = morpheus_network::stack::rx_packet_count() as u64;
89+
out.tcp_active = state::tcp_active_count();
90+
0
91+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
mod activate;
2+
mod config;
3+
mod nic;
4+
mod state;
5+
mod tcp;
6+
mod udp_dns;
7+
8+
pub unsafe fn init_userspace_network_activation(
9+
dma: morpheus_network::dma::DmaRegion,
10+
tsc_freq: u64,
11+
) {
12+
activate::init_userspace_network_activation(dma, tsc_freq);
13+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
use morpheus_network::device::NetworkDevice;
2+
3+
use super::state;
4+
5+
pub(super) unsafe fn log_pci_network_candidates() {
6+
let mut found = 0u32;
7+
for bus in 0..=255u8 {
8+
for dev in 0..32u8 {
9+
for func in 0..8u8 {
10+
let addr = morpheus_hwinit::PciAddr::new(bus, dev, func);
11+
let vendor = morpheus_hwinit::pci_cfg_read16(addr, 0x00);
12+
if vendor == 0xFFFF {
13+
if func == 0 {
14+
break;
15+
}
16+
continue;
17+
}
18+
19+
let class = morpheus_hwinit::pci_cfg_read8(addr, 0x0B);
20+
let subclass = morpheus_hwinit::pci_cfg_read8(addr, 0x0A);
21+
if class != 0x02 {
22+
if func == 0 {
23+
let header = morpheus_hwinit::pci_cfg_read8(addr, 0x0E);
24+
if (header & 0x80) == 0 {
25+
break;
26+
}
27+
}
28+
continue;
29+
}
30+
31+
let device = morpheus_hwinit::pci_cfg_read16(addr, 0x02);
32+
found = found.wrapping_add(1);
33+
morpheus_hwinit::serial::puts("[INFO] [NET] pci net candidate bdf=");
34+
morpheus_hwinit::serial::put_hex64(
35+
((bus as u64) << 16) | ((dev as u64) << 8) | func as u64,
36+
);
37+
morpheus_hwinit::serial::puts(" ven=");
38+
morpheus_hwinit::serial::put_hex64(vendor as u64);
39+
morpheus_hwinit::serial::puts(" dev=");
40+
morpheus_hwinit::serial::put_hex64(device as u64);
41+
morpheus_hwinit::serial::puts(" sub=");
42+
morpheus_hwinit::serial::put_hex64(subclass as u64);
43+
morpheus_hwinit::serial::puts("\n");
44+
45+
if func == 0 {
46+
let header = morpheus_hwinit::pci_cfg_read8(addr, 0x0E);
47+
if (header & 0x80) == 0 {
48+
break;
49+
}
50+
}
51+
}
52+
}
53+
}
54+
55+
if found == 0 {
56+
morpheus_hwinit::serial::log_warn("NET", 953, "pci scan found zero class-0x02 devices");
57+
} else {
58+
morpheus_hwinit::serial::log_info("NET", 954, "pci net candidates logged");
59+
}
60+
}
61+
62+
pub(super) unsafe fn user_net_tx(frame: *const u8, len: usize) -> i64 {
63+
let Some(driver) = state::user_net_driver_mut() else {
64+
return -1;
65+
};
66+
let frame = core::slice::from_raw_parts(frame, len);
67+
if driver.transmit(frame).is_ok() {
68+
0
69+
} else {
70+
-1
71+
}
72+
}
73+
74+
pub(super) unsafe fn user_net_rx(buf: *mut u8, buf_len: usize) -> i64 {
75+
let Some(driver) = state::user_net_driver_mut() else {
76+
return -1;
77+
};
78+
let buf = core::slice::from_raw_parts_mut(buf, buf_len);
79+
match driver.receive(buf) {
80+
Ok(Some(n)) => n as i64,
81+
Ok(None) => 0,
82+
Err(_) => -1,
83+
}
84+
}
85+
86+
pub(super) unsafe fn user_net_link_up() -> i64 {
87+
let Some(driver) = state::user_net_driver_mut() else {
88+
return 0;
89+
};
90+
driver.link_up() as i64
91+
}
92+
93+
pub(super) unsafe fn user_net_mac(out: *mut u8) -> i64 {
94+
let Some(driver) = state::user_net_driver_mut() else {
95+
return -1;
96+
};
97+
let mac = driver.mac_address();
98+
core::ptr::copy_nonoverlapping(mac.as_ptr(), out, 6);
99+
0
100+
}
101+
102+
pub(super) unsafe fn user_net_refill() -> i64 {
103+
let Some(driver) = state::user_net_driver_mut() else {
104+
return -1;
105+
};
106+
driver.refill_rx_queue();
107+
driver.collect_tx_completions();
108+
0
109+
}
110+
111+
pub(super) unsafe fn user_net_ctrl(_cmd: u32, _arg: u64) -> i64 {
112+
-1
113+
}

0 commit comments

Comments
 (0)