Keyboard lights, TLB shootdowns, battery in sysfs, /proc/pid/maps

Caps, Num and Scroll Lock now light their LEDs on PS/2 and USB keyboards,
share one state between keyboards, and stop toggling on key repeat. X sets
them through evdev writes while it holds the keyboard.

Unmapping memory in a process with threads on other CPUs now flushes their
TLBs with an IPI. Without it a freed page stayed reachable through stale
translations, which corrupted Epiphany's heap on SMP.

ACPI batteries and AC adapters appear under /sys/class/power_supply.
/proc/<pid>/maps lists file mappings, and a process killed by a fault
names the file and offset it died in. r8169 gets a 256-entry RX ring.

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 13:43:27 +01:00
commit 438e7af141
18 changed files with 945 additions and 9 deletions

View file

@ -128,7 +128,12 @@ struct rtl_desc {
#define DESC_LS 0x10000000 // last fragment
#define DESC_LEN 0x00003FFF
#define NRX 32
// 256, as the e1000 has. It was 32, and TCP advertises a 256 KB window --
// some 180 full frames in flight -- which a gigabit link fills 32 slots with
// in under half a millisecond. Everything past them was dropped, TCP read the
// drops as congestion, and a download on the laptop crawled: apk sat on its
// first index for minutes. The chip takes up to 1024.
#define NRX 256
#define NTX 32
#define BUFSZ 2048 // one frame, with room for a VLAN tag

View file

@ -43,6 +43,7 @@ struct hfield {
struct hid {
int in_use;
struct usb_dev *dev;
int proto; // USB_HID_PROTO_KEYBOARD, _MOUSE or _TABLET
uchar prev[8]; // the previous report, for edge detection
@ -248,6 +249,13 @@ keyboard_report(struct hid *h, const uchar *rep, int len)
keyboard_events(h->prev, rep);
// A lock key let go: the next press toggles again.
for(i = 2; i < 8; i++){
uchar was = h->prev[i];
if((was == 0x39 || was == 0x53 || was == 0x47) && !was_down(rep, was))
kbd_lock_key(was == 0x39 ? CAPSLOCK : was == 0x53 ? NUMLOCK : SCROLLLOCK, 0);
}
// Grabbed: the events above still went to /dev/input/event0, but nothing
// reaches the console. Note prev[] is updated before returning, or the next
// report would look like every held key had just been pressed again.
@ -264,11 +272,19 @@ keyboard_report(struct hid *h, const uchar *rep, int len)
if(was_down(h->prev, usage))
continue; // still held from last time, not a new press
if(usage == 0x39 || usage == 0x53 || usage == 0x47){
kbd_lock_key(usage == 0x39 ? CAPSLOCK : usage == 0x53 ? NUMLOCK : SCROLLLOCK, 1);
continue;
}
if(usage >= 0x39){
if((c = hid_special(usage, mods)) == 0)
continue;
} else {
c = (mods & HID_MOD_SHIFT) ? hid_shifted[usage] : hid_unshifted[usage];
// Caps lock shifts letters only, as on every keyboard.
int shifted = (mods & HID_MOD_SHIFT) != 0;
if((kbd_lock_state() & CAPSLOCK) && usage >= 0x04 && usage <= 0x1D)
shifted = !shifted;
c = shifted ? hid_shifted[usage] : hid_unshifted[usage];
if(c == 0)
continue;
}
@ -305,6 +321,39 @@ keyboard_report(struct hid *h, const uchar *rep, int len)
consoleintr(usb_kbd_getc);
}
// The lights every USB keyboard should show, in HID's order (Num, Caps,
// Scroll), and what was last sent. Set from interrupt context; sent from
// usb_hid_tick, which runs on a thread and may wait for a control transfer.
static volatile int leds_want = -1;
static int leds_sent = -1;
void
hid_leds_want(int bits)
{
leds_want = bits;
}
static void
hid_send_leds(int bits)
{
for(int i = 0; i < NHID; i++){
struct hid *h = &hids[i];
if(!h->in_use || !h->dev ||
!(h->rkbd || h->proto == USB_HID_PROTO_KEYBOARD))
continue;
// SET_REPORT, output report: one byte of lights, under the keyboard's
// report ID when its reports carry one.
struct usb_setup s;
uchar b = (uchar)bits;
s.bmRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
s.bRequest = 0x09;
s.wValue = (2 << 8) | (h->rkbd ? h->kbd_id : 0);
s.wIndex = h->dev->iface.bInterfaceNumber;
s.wLength = 1;
h->dev->ops->control(h->dev, &s, &b, 1);
}
}
void
usb_hid_tick(void)
{
@ -312,6 +361,11 @@ usb_hid_tick(void)
if(!kqinit)
return;
int want = leds_want;
if(want >= 0 && want != leds_sent){
leds_sent = want;
hid_send_leds(want);
}
acquire(&kqlock);
if(krep.c && (int)(ticks - krep.at) >= 0){
c = krep.c;
@ -870,7 +924,9 @@ hid_probe(struct usb_dev *dev)
return -1;
h->in_use = 1;
h->dev = dev;
dev->drvdata = h;
leds_sent = -1; // a new keyboard gets the current lights
dev->complete = hid_complete;
// Arm the first transfer. Until a TRB is waiting on the endpoint the device