};
cap IRQDest {
+ /* IRQ Destination capability.
+ Represents a slot in a CPUs int vector table.
+ Can be connected to a LMP endpoint to recv this interrupt. */
eq uint64 cpu;
eq uint64 vector;
};
cap IRQSrc {
- /* IRQ capability. Represents an interrupt vector at an interrupt controller. */
- eq uint64 vector;
- eq uint64 controller;
+ /* IRQ Source capability.
+ Represents an interrupt source. It contains a range of interrupt
+ source numbers. */
+ eq uint64 vec_start;
+ eq uint64 vec_end;
};
cap IO {
return ret.error;
}
-static inline errval_t invoke_irqsrc_get_vector(struct capref irqcap, uint32_t * out_vec)
+static inline errval_t invoke_irqsrc_get_vec_start(struct capref irqcap, uint32_t * out_vec)
{
- struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVector);
- *out_vec = ret.value;
- return ret.error;
+ USER_PANIC("NYI");
+ return LIB_ERR_NOT_IMPLEMENTED;
+}
+
+static inline errval_t invoke_irqsrc_get_vec_end(struct capref irqcap, uint32_t * out_vec)
+{
+ USER_PANIC("NYI");
+ return LIB_ERR_NOT_IMPLEMENTED;
}
static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap, struct capref dest_cap)
{
- uint8_t dcn_vbits = get_cnode_valid_bits(dest_cap);
- capaddr_t dcn_addr = get_cnode_addr(dest_cap);
- struct sysret ret = cap_invoke4(irqcap, IRQTableCmd_AllocDestCap, dcn_vbits, dcn_addr, dest_cap.slot);
- return ret.error;
+ USER_PANIC("NYI");
+ return LIB_ERR_NOT_IMPLEMENTED;
}
/**
return ret.error;
}
-static inline errval_t invoke_irqsrc_get_vector(struct capref irqcap, uint64_t * out_vec)
+static inline errval_t invoke_irqsrc_get_vec_start(struct capref irqcap, uint64_t * out_vec)
{
- struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVector);
+ struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVecStart);
+ *out_vec = ret.value;
+ return ret.error;
+}
+
+static inline errval_t invoke_irqsrc_get_vec_end(struct capref irqcap, uint64_t * out_vec)
+{
+ struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVecEnd);
*out_vec = ret.value;
return ret.error;
}
errval_t sys_debug_hardware_timer_hertz_read(uintptr_t* ret);
errval_t sys_debug_hardware_global_timer_read(uint64_t *ret);
errval_t sys_debug_get_apic_ticks_per_sec(uint32_t *ret);
-errval_t sys_debug_create_irq_src_cap(struct capref cap, uint16_t gsi);
+errval_t sys_debug_create_irq_src_cap(struct capref cap, uint64_t start, uint64_t end);
#ifdef ENABLE_FEIGN_FRAME_CAP
errval_t sys_debug_feign_frame_cap(struct capref slot, lpaddr_t base,
*/
enum irqsrc_cmd {
- IRQSrcCmd_GetVector ///< Return vector and controller saved in this cap.
+ IRQSrcCmd_GetVecStart, ///< Return vector range start
+ IRQSrcCmd_GetVecEnd ///< Return vector range high
};
}
}
-errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr, uint16_t gsi)
+errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn,
+ capaddr_t out_cap_addr, uint64_t start, uint64_t end)
{
// This method is a hack to forge a irq src cap for the given GSI targeting the ioapic
errval_t err;
memset(&out_cap, 0, sizeof(struct cte));
out_cap.cap.type = ObjType_IRQSrc;
- out_cap.cap.u.irqsrc.vector = gsi;
- const uint32_t ioapic_controller_id = 1000;
- out_cap.cap.u.irqsrc.controller = ioapic_controller_id;
+ out_cap.cap.u.irqsrc.vec_start = start;
+ out_cap.cap.u.irqsrc.vec_end = end;
struct cte * cn;
err = caps_lookup_slot(&dcb_current->cspace.cap, dcn, dcn_vbits, &cn, CAPRIGHTS_WRITE);
}
}
-errval_t irq_debug_create_src_cap(uint8_t dcn_level, capaddr_t dcn, capaddr_t out_cap_addr, uint16_t gsi)
+/* Create a src cap for one specific interrupt. vec_start = vec_end = gsi */
+errval_t irq_debug_create_src_cap(uint8_t dcn_level, capaddr_t dcn,
+ capaddr_t out_cap_addr, uint64_t start, uint64_t end)
{
- // This method is a hack to forge a irq src cap for the given GSI targeting the ioapic
errval_t err;
struct cte out_cap;
memset(&out_cap, 0, sizeof(struct cte));
out_cap.cap.type = ObjType_IRQSrc;
- out_cap.cap.u.irqsrc.vector = gsi;
- const uint32_t ioapic_controller_id = 1000;
- out_cap.cap.u.irqsrc.controller = ioapic_controller_id;
+ out_cap.cap.u.irqsrc.vec_start = start;
+ out_cap.cap.u.irqsrc.vec_end = end;
struct cte * cn;
- err = caps_lookup_slot(&dcb_current->cspace.cap, dcn, dcn_level, &cn, CAPRIGHTS_WRITE);
+ err = caps_lookup_slot(&dcb_current->cspace.cap, dcn, dcn_level, &cn,
+ CAPRIGHTS_WRITE);
if(err_is_fail(err)){
return err;
}
return SYSRET(SYS_ERR_OK);
}
-static struct sysret handle_irqsrc_get_vector(struct capability * to, int cmd,
+static struct sysret handle_irqsrc_get_vec_start(struct capability * to, int cmd,
uintptr_t *args)
{
struct sysret ret;
ret.error = SYS_ERR_OK;
- ret.value = to->u.irqsrc.vector;
+ ret.value = to->u.irqsrc.vec_start;
+ return ret;
+
+}
+
+static struct sysret handle_irqsrc_get_vec_end(struct capability * to, int cmd,
+ uintptr_t *args)
+{
+ struct sysret ret;
+ ret.error = SYS_ERR_OK;
+ ret.value = to->u.irqsrc.vec_end;
return ret;
}
[IRQDestCmd_GetCpu] = handle_irqdest_get_cpu
},
[ObjType_IRQSrc] = {
- [IRQSrcCmd_GetVector] = handle_irqsrc_get_vector,
+ [IRQSrcCmd_GetVecStart] = handle_irqsrc_get_vec_start,
+ [IRQSrcCmd_GetVecEnd] = handle_irqsrc_get_vec_end
},
[ObjType_IRQTable] = {
[IRQTableCmd_Alloc] = handle_irq_table_alloc,
break;
case DEBUG_CREATE_IRQ_SRC_CAP:
- retval.error = irq_debug_create_src_cap(arg1, args[0], args[1], args[2]);
+ retval.error = irq_debug_create_src_cap(arg1, args[0], args[1],
+ args[2], args[3]);
break;
default:
errval_t irq_table_delete(unsigned int nidt);
struct kcb;
errval_t irq_table_notify_domains(struct kcb *kcb);
-errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr);
-errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr, uint16_t gsi);
+errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn,
+ capaddr_t out_cap_addr);
+errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn,
+ capaddr_t out_cap_addr, uint64_t start, uint64_t end);
#endif
return sr.error;
}
-errval_t sys_debug_create_irq_src_cap(struct capref cap, uint16_t gsi)
+errval_t sys_debug_create_irq_src_cap(struct capref cap, uint64_t start,
+ uint64_t end)
{
uint8_t dcn_level = get_cnode_level(cap);
capaddr_t dcn_addr = get_cnode_addr(cap);
- struct sysret sr = syscall6(SYSCALL_DEBUG, DEBUG_CREATE_IRQ_SRC_CAP,
- dcn_level, dcn_addr, cap.slot, gsi);
+ struct sysret sr = syscall7(SYSCALL_DEBUG, DEBUG_CREATE_IRQ_SRC_CAP,
+ dcn_level, dcn_addr, cap.slot, start, end);
return sr.error;
}
return sr.error;
}
-errval_t sys_debug_create_irq_src_cap(struct capref cap, uint16_t gsi)
+errval_t sys_debug_create_irq_src_cap(struct capref cap, uint64_t start,
+ uint64_t end)
{
assert(!"NYI");
return SYS_ERR_OK;
return sr.error;
}
-errval_t sys_debug_create_irq_src_cap(struct capref cap, uint16_t gsi)
+errval_t sys_debug_create_irq_src_cap(struct capref cap, uint64_t start, uint64_t end)
{
// XXX: check this
uint8_t dcn_level = get_cnode_level(cap);
capaddr_t dcn_addr = get_cnode_addr(cap);
- struct sysret sr = syscall6(SYSCALL_DEBUG, DEBUG_CREATE_IRQ_SRC_CAP, dcn_level, dcn_addr,
- cap.slot, gsi);
+ struct sysret sr = syscall7(SYSCALL_DEBUG, DEBUG_CREATE_IRQ_SRC_CAP, dcn_level, dcn_addr,
+ cap.slot, start, end);
return sr.error;
}
return snprintf(buf, len, "IRQTable cap");
case ObjType_IRQSrc:
- return snprintf(buf, len, "IRQSrc cap (vec: %"PRIu64")",
- cap->u.irqsrc.vector);
+ return snprintf(buf, len, "IRQSrc cap (vec: %"PRIu64"-%"PRIu64")",
+ cap->u.irqsrc.vec_start, cap->u.irqsrc.vec_end);
case ObjType_IRQDest:
return snprintf(buf, len, "IRQDest cap (vec: %"PRIu64", cpu: %"PRIu64")",
errval_t err;
uint64_t int_src_num = INVALID_VECTOR;
- err = invoke_irqsrc_get_vector(intsource, &int_src_num);
+ err = invoke_irqsrc_get_vec_start(intsource, &int_src_num);
+ uint64_t int_src_num_high = INVALID_VECTOR;
+ err = invoke_irqsrc_get_vec_end(intsource, &int_src_num_high);
+
+ // TODO: Maybe it would be better to pass a IRQ offset into
+ // the capability to the route call. So that the client
+ // doesnt have to do retype all the time.
+ if(int_src_num != int_src_num_high){
+ err = SYS_ERR_IRQ_INVALID;
+ DEBUG_ERR(err, "IrqSrc cap must contain only one vec");
+ b->tx_vtbl.route_response(b, NOP_CONT, err);
+ return;
+ }
+
assert(err_is_ok(err));
uint64_t dest_vec = INVALID_VECTOR;
return err;
}
+ // For now, we just use the first vector passed to the driver.
uint64_t gsi = INVALID_VECTOR;
- err = invoke_irqsrc_get_vector(irq_src_cap, &gsi);
+ err = invoke_irqsrc_get_vec_start(irq_src_cap, &gsi);
if (err_is_fail(err)) {
DEBUG_ERR(err, "Could not lookup GSI vector");
return err;
int_arg.int_range_start = 1000;
int_arg.int_range_end = 1004;
coreid_t offset;
- err = skb_read_output("driver(%"SCNu8", %"SCNu8", %"SCNu8", %[^,], %"SCNu8")", &core, &multi, &offset,
- binary_name, &int_model_in);
+ err = skb_read_output("driver(%"SCNu8", %"SCNu8", %"SCNu8", %[^,], "
+ "%"SCNu8")", &core, &multi, &offset, binary_name, &int_model_in);
if(err_is_fail(err)){
USER_PANIC_SKB_ERR(err, "Could not parse SKB output.\n");
}
if(nl) *nl = '\0';
intcaps_debug_msg[99] = '\0';
+ uint64_t start=0, end=0;
+ err = skb_read_output("%"SCNu64", %"SCNu64, &start, &end);
if(err_is_fail(err)){
DEBUG_SKB_ERR(err, "Could not parse SKB output. Not starting driver.\n");
goto out;
}
- struct list_parser_status pa_sta;
- skb_read_list_init(&pa_sta);
- int int_num;
+
struct cnoderef argnode_ref;
err = cnode_create_l2(&driver_arg.arg_caps, &argnode_ref);
-
if(err_is_fail(err)){
- USER_PANIC_ERR(err, "Could not create int_src cap");
+ USER_PANIC_ERR(err, "Could not cnode_create_l2");
}
- for(int i=0; skb_read_list(&pa_sta, "int(%d)", &int_num); i++){
- //Works
- KALUGA_DEBUG("Interrupt for driver: %d\n", int_num);
- struct capref cap;
- cap.cnode = argnode_ref;
- cap.slot = i;
- err = sys_debug_create_irq_src_cap(cap, int_num);
-
- if(err_is_fail(err)){
- USER_PANIC_ERR(err, "Could not create int_src cap");
- }
+ struct capref cap;
+ cap.cnode = argnode_ref;
+ cap.slot = 0;
+ err = sys_debug_create_irq_src_cap(cap, start, end);
+ if(err_is_fail(err)){
+ USER_PANIC_ERR(err, "Could not create int_src cap");
}
} else if(int_arg.model == INT_MODEL_MSI){
KALUGA_DEBUG("Starting driver (%s) with MSI interrupts\n", binary_name);
struct capref cap;
cap.cnode = argnode_ref;
cap.slot = 0;
- err = sys_debug_create_irq_src_cap(cap, int_nr);
+ err = sys_debug_create_irq_src_cap(cap, int_nr, int_nr);
if(err_is_fail(err)){
DEBUG_ERR(err, "Could not create int_src cap");
struct capref cap;
cap.cnode = argnode_ref;
cap.slot = 0;
- err = sys_debug_create_irq_src_cap(cap, int_nr);
+ err = sys_debug_create_irq_src_cap(cap, int_nr, int_nr);
if(err_is_fail(err)){
DEBUG_ERR(err, "Could not create int_src cap");
PCI_DEBUG("pci: Interrupt enabled.\n");
- err = sys_debug_create_irq_src_cap(cap, irq);
+ err = sys_debug_create_irq_src_cap(cap, irq, irq);
if (err_is_fail(err)) {
USER_PANIC_ERR(err, "create irq src cap failed.");
}
% when using legacy interrupts, the PCI card does not need a controller
% however it needs to be aware of the int numbers to use.
+% This function returns always only one interrupt, but for compatibility,
+% it returns a Lo,Hi tuple
% A = addr(Bus,Device,Function)
-get_pci_legacy_int_range(A, Li) :-
- ((
- device(_, A, _, _, _, _, _, Pin),
- find_prt_entry(Pin, A, X),
- prt_entry_to_num(X, IntNu),
- LiT = [int(IntNu)]
- ) ; (
- LiT = [none]
- )),
- filter_none(LiT,Li).
+% LiR = (Lo,Hi)
+get_pci_legacy_int_range(A, (Lo,Hi)) :-
+ device(_, A, _, _, _, _, _, Pin),
+ find_prt_entry(Pin, A, X),
+ prt_entry_to_num(X, IntNu),
+ Lo = IntNu,
+ Hi = IntNu.
% Translates fixed x86 legacy interrupt numbers to internal interrupt source number.
% It first translates Legacy to GSI, then GSI to internal.