Demand paging, the RTL8168H, links that come up late, and Ctrl+Alt+F1..F12

- Anonymous memory can be reserved without being backed: large mappings,
  MAP_NORESERVE and PROT_NONE are recorded and each page appears, zeroed,
  on first touch -- from trap() for the program, from uva2ka() for the
  kernel on its behalf. WebKit reserves 4 GB at start and touches a sliver;
  backing it all failed with ENOMEM and Epiphany aborted.
- r8169: the 8168G generation and later (the laptop's 8168H, XID 541) are
  taken from the firmware's out-of-band mode, get their PLL powered, the
  receive gate opened, and their PHY reached through the OCP window. The
  PHY's power-down bit is cleared; the old code kept it while restarting
  autonegotiation. Untested on the hardware so far.
- The network thread follows each device's link into lwIP. The link was
  read once at attach, 0.02 s into boot; real autonegotiation takes
  seconds, so on hardware the interface stayed down for good.
- Twelve terminals, switched with Ctrl+Alt+F1..F12 by default: the keys X
  uses, so the console and the desktop agree. AltGr+F-key is gone from
  the defaults (chvt -c altgr+F brings it back).
- SO_PASSCRED on Unix sockets, with SCM_CREDENTIALS delivered by recvmsg.
  WebKit sets it on its IPC sockets and aborted when refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-25 11:27:48 +01:00
commit 54b25708c3
24 changed files with 4166 additions and 68 deletions

View file

@ -259,3 +259,28 @@ net_eth_poll(void)
}
return moved;
}
// Follow each device's link into lwIP.
//
// The link was read once, at attach, and never again. Under QEMU it is up
// before the driver asks; on a real network autonegotiation takes two or
// three seconds, so attach saw it down and the interface stayed down for
// good -- no DHCP, no traffic, the cable plugged in and nothing to show for
// it. Bringing the link up also restarts DHCP (lwIP does that itself).
void
net_eth_link_check(void)
{
for (int k = 0; k < nifs; k++) {
struct eth_if *e = &ifs[k];
if (!e->used)
continue;
int up = netdev_link_up(e->dev) != 0;
if (up == (netif_is_link_up(&e->netif) != 0))
continue;
if (up)
netif_set_link_up(&e->netif);
else
netif_set_link_down(&e->netif);
klog("net: %s link %s\n", e->dev->name, up ? "up" : "down");
}
}

View file

@ -292,12 +292,19 @@ net_thread(void)
// One bit per interface, so a second one binding later is announced too.
uint link_checked = 0;
for (;;) {
int moved;
lwip_sys_lock();
moved = net_eth_poll();
sys_check_timeouts();
// A quarter of a second is quick enough to notice a cable, and a
// register read per interface that often costs nothing.
if (ticks - link_checked >= 25) {
link_checked = ticks;
net_eth_link_check();
}
// Loopback has no driver and no interrupt: a packet sent to 127.0.0.1
// sits on the loopif's queue until something drains it. With NO_SYS=1
// that something is this thread.

View file

@ -271,6 +271,7 @@ sockopt_set(struct socket *s, int level, int name, int val)
case SO_REUSEADDR: s->o_reuseaddr = !!val; break;
case SO_KEEPALIVE: s->o_keepalive = !!val; break;
case SO_BROADCAST: s->o_broadcast = !!val; break;
case 16: s->o_passcred = !!val; break; // SO_PASSCRED
// Accepted and left at the size we have. Not the same lie as before:
// Linux is explicitly free to clamp these, and sockopt_get below reports
// the real figure rather than the requested one.
@ -313,6 +314,7 @@ sockopt_get(struct socket *s, int level, int name, int *out)
case SO_REUSEADDR: *out = s->o_reuseaddr; break;
case SO_KEEPALIVE: *out = s->o_keepalive; break;
case SO_BROADCAST: *out = s->o_broadcast; break;
case 16: *out = s->o_passcred; break; // SO_PASSCRED
// The real buffer, not a number somebody asked for.
case SO_SNDBUF:
case SO_RCVBUF: *out = SOCKBUF; break;
@ -1025,6 +1027,12 @@ socksendto(struct socket *s, char *buf, int n, uint addr, ushort port)
return sockwrite(s, buf, n);
}
int
sock_passcred(struct socket *s)
{
return s->domain != AF_INET && s->o_passcred;
}
// SO_PEERCRED: the credentials recorded for the far end of a connected Unix
// socket. -1 if there is no far end.
int