diff --git a/boot-programs/gpio.ccp b/boot-programs/gpio.ccp index a36f2e8..ed30971 100644 --- a/boot-programs/gpio.ccp +++ b/boot-programs/gpio.ccp @@ -60,13 +60,13 @@ enum cap_type: CAP_PWM NUM_EVENT_TYPES -static Caps events = Cap (0, 6) +static unsigned events static void event (event_type type, unsigned data): - Cap (2, type - 32).invoke (data) + Cap (events, type - 32).invoke (data) static void set_cb (Cap cap, event_type type): - cap.clone (events, type - 32) + cap.clone (Cap (events, type - 32)) class DevKeyboard: static unsigned const encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS] @@ -255,10 +255,13 @@ class Pwm: // TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything. Num start (): - __my_memory.create_caps (NUM_EVENT_TYPES - 32).clone (__my_caps, 6) map_gpio () map_pwm0 () + Caps e = __my_memory.create_caps (NUM_EVENT_TYPES - 32) + events = e.use () + free_cap (e) + DevKeyboard kbd Touchpad tp Lockleds leds @@ -268,14 +271,15 @@ Num start (): GPIO_GPIER (GPIO_KBD_ROW_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) | GPIO_KBD_ROW_MASK Kernel::register_interrupt (IRQ_GPIO0) - Caps c (0, 7) - __my_memory.create_caps (4).clone (__my_caps, 7) - __my_receiver.create_capability (CAP_KEYBOARD).clone (c, 0) - __my_receiver.create_capability (CAP_TOUCHPAD).clone (c, 1) - __my_receiver.create_capability (CAP_LOCKLEDS).clone (c, 2) - __my_receiver.create_capability (CAP_PWM).clone (c, 3) + Caps c = __my_memory.create_caps (4) + unsigned init_slot = c.use () + __my_receiver.create_capability (CAP_KEYBOARD, Cap (init_slot, 0)) + __my_receiver.create_capability (CAP_TOUCHPAD, Cap (init_slot, 1)) + __my_receiver.create_capability (CAP_LOCKLEDS, Cap (init_slot, 2)) + __my_receiver.create_capability (CAP_PWM, Cap (init_slot, 3)) __my_parent.invoke (c, INIT_SET_GPIO) + free_cap (c) if kbd.is_scanning (): __my_receiver.set_alarm (ALARM_INTERVAL) diff --git a/invoke.ccp b/invoke.ccp index a7edab7..cbcec51 100644 --- a/invoke.ccp +++ b/invoke.ccp @@ -348,11 +348,22 @@ static void thread_invoke (unsigned cmd, unsigned target, Num cap_protected, kCa if value: *value = (*value & ~c->data[1].h) | (c->data[1].l & c->data[1].h) break + case Thread::USE_SLOT: + if c->data[1].l >= thread->slots || c->caps->size < 2: + reply_num (~0) + return + // FIXME: This doesn't allow using a fake caps. + if (unsigned)c->caps->cap (1)->target != (CAPTYPE_CAPS | CAP_MASTER) && (unsigned)c->caps->cap (1)->target != (CAPTYPE_CAPS | Caps::USE): + reply_num (~0) + return + thread->fill_slot (c->data[1].l, (kCaps *)c->caps->cap (1)->cap_protected.l) + reply_num (0) + return case Thread::SCHEDULE: do_schedule = true return if !(thread->flags & Thread::PRIV): - reply_num (~0) + reply_num (ERR_INVALID_OPERATION) return switch cmd: case Thread::PRIV_REGISTER_INTERRUPT: diff --git a/iris.hhp b/iris.hhp index ec75fd8..7d0cda5 100644 --- a/iris.hhp +++ b/iris.hhp @@ -160,20 +160,16 @@ struct Cap: struct OMessage inline void invoke (IMessage const *i, OMessage *o) inline void call (IMessage *i, OMessage *o) - inline void invoke (Cap c, Num d0 = 0, Num d1 = 0, Caps caps = __tmp_caps) + inline void invoke (Cap c, Num d0 = 0, Num d1 = 0, unsigned oslot = __tmp_slot) inline void invoke (Num d0 = 0, Num d1 = 0) - inline Num call (Cap c, Num d0 = 0, Num d1 = 0, Caps caps = __tmp_caps, unsigned slot = ~0) - inline Num call (Num d0 = 0, Num d1 = 0, Caps caps = __tmp_caps, unsigned slot = ~0) - inline void clone (Caps caps, unsigned idx) - -struct Caps : public Cap: - Caps (unsigned slot, unsigned idx) : Cap (slot, idx): - Caps (Cap c = Cap ()) : Cap (c): + inline Num call (Cap c, Num d0 = 0, Num d1 = 0, unsigned oslot = __tmp_slot, unsigned islot = ~0) + inline Num call (Num d0 = 0, Num d1 = 0, unsigned oslot = __tmp_slot, unsigned islot = ~0) + inline void clone (Cap target) struct Cap::IMessage: Num data[2] - Caps caps - unsigned slot + unsigned islot + unsigned oslot unsigned num, first Cap *set struct Cap::OMessage: @@ -239,11 +235,11 @@ void Cap::invoke (IMessage const *i, OMessage *o): void Cap::call (IMessage *i, OMessage *o): i->set[0] = *this __my_call.copy ().invoke (i, o) -void Cap::invoke (Cap c, Num d0, Num d1, Caps caps): +void Cap::invoke (Cap c, Num d0, Num d1, unsigned oslot): IMessage i OMessage o - i.slot = ~0 - i.caps = caps + i.islot = ~0 + i.oslot = oslot Cap cs[2] cs[0] = c i.set = cs @@ -255,51 +251,51 @@ void Cap::invoke (Cap c, Num d0, Num d1, Caps caps): void Cap::invoke (Num d0, Num d1): IMessage i OMessage o - i.caps = Cap () - i.slot = ~0 + i.oslot = ~0 + i.islot = ~0 i.num = 0 i.data[0] = d0 i.data[1] = d1 invoke (&i, &o) -Num Cap::call (Cap c, Num d0, Num d1, Caps caps, unsigned slot): +Num Cap::call (Cap c, Num d0, Num d1, unsigned oslot, unsigned islot): IMessage i OMessage o Cap cs[2] cs[1] = c i.set = cs - i.caps = caps - i.slot = slot + i.oslot = oslot + i.islot = islot i.num = 2 i.first = 0 i.data[0] = d0 i.data[1] = d1 invoke (&i, &o) return o.data[0] -Num Cap::call (Num d0, Num d1, Caps caps, unsigned slot): +Num Cap::call (Num d0, Num d1, unsigned oslot, unsigned islot): IMessage i OMessage o Cap cs[2] i.set = cs - i.caps = caps - i.slot = slot + i.oslot = oslot + i.islot = islot i.num = 2 i.first = 0 i.data[0] = d0 i.data[1] = d1 invoke (&i, &o) return o.data[0] -void Cap::clone (Caps caps, unsigned idx): +void Cap::clone (Cap target): IMessage i OMessage o Cap c = this->copy () i.set = &c - i.caps = caps - i.first = idx + i.oslot = target.slot () + i.first = target.idx () i.num = 1 - i.slot = ~0 + i.islot = ~0 i.data[0] = 0 i.data[1] = 0 - invoke (&i, &o) + Cap ().invoke (&i, &o) struct Receiver : public Cap: Receiver (unsigned slot, unsigned idx) : Cap (slot, idx): @@ -351,6 +347,7 @@ struct Thread : public Cap: // Info details are arch-specific. GET_INFO = 1 SET_INFO + USE_SLOT SCHEDULE PRIV_ALLOC_RANGE PRIV_PHYSICAL_ADDRESS @@ -392,6 +389,21 @@ struct Thread : public Cap: set_flags (run ? RUNNING : 0, RUNNING) void wait (bool wait): set_flags (wait ? WAITING : 0, WAITING) + inline unsigned use (Caps caps, unsigned slot = alloc_slot ()) + +struct Caps : public Cap: + Caps (unsigned slot, unsigned idx) : Cap (slot, idx): + Caps (Cap c = Cap ()) : Cap (c): + enum request: + // Not an operation; this capability can be used in Thread::USE_SLOT. + USE = 1 + unsigned use (unsigned slot = alloc_slot ()): + __my_thread.use (*this, slot) + return slot + +unsigned Thread::use (Caps caps, unsigned slot): + invoke (caps, CAP_MASTER_DIRECT | USE_SLOT, slot) + return slot struct Page : public Cap: Page (unsigned slot, unsigned idx) : Cap (slot, idx): @@ -476,9 +488,9 @@ struct Memory : public Cap: invoke (CAP_MASTER_DIRECT | SET_LIMIT, limit) struct Kernel: - static void wait (Cap::OMessage *o, unsigned slot = __tmp_slot): + static void wait (Cap::OMessage *o, unsigned islot = __tmp_slot): Cap::IMessage i - i.slot = slot + i.islot = islot i.num = 0 Cap ().copy ().invoke (&i, o) static void schedule (): diff --git a/mips/interrupts.ccp b/mips/interrupts.ccp index 6572abe..feb1c8c 100644 --- a/mips/interrupts.ccp +++ b/mips/interrupts.ccp @@ -134,8 +134,8 @@ static void arch_invoke (): if num > 10: num = 10 bool copy - if old_current->arch.s0 < old_current->slots: - msg.caps = old_current->caps[old_current->arch.s0] + if old_current->arch.s1 < old_current->slots: + msg.caps = old_current->caps[old_current->arch.s1] if msg.caps && first < msg.caps->size: for unsigned i = first; i < num && i < msg.caps->size; ++i: msg.caps->cap (i)->invalidate () @@ -147,7 +147,7 @@ static void arch_invoke (): else: msg.caps = NULL if wait: - old_current->recv_slot = old_current->arch.s1 + old_current->recv_slot = old_current->arch.s0 old_current->wait () if !target: if (old_current->arch.v0 & ~CAP_COPY) != ~CAP_COPY: