HelenOS sources
This source file includes following definitions.
- virt_init
- virt_irq_exception
- virt_output_init
- virt_input_init
- virt_enable_vtimer_irq
- virt_get_irq_count
- virt_get_platform_name
#include <arch/mach/virt/virt.h>
#include <console/console.h>
#include <genarch/drivers/gicv2/gicv2.h>
#include <genarch/drivers/pl011/pl011.h>
#include <genarch/srln/srln.h>
#include <mm/km.h>
#include <sysinfo/sysinfo.h>
#define VIRT_VTIMER_IRQ 27
#define VIRT_UART_IRQ 33
#define VIRT_GIC_DISTR_ADDRESS 0x08000000
#define VIRT_GIC_CPUI_ADDRESS 0x08010000
#define VIRT_UART_ADDRESS 0x09000000
static void virt_init(void);
static void virt_irq_exception(unsigned int exc_no, istate_t *istate);
static void virt_output_init(void);
static void virt_input_init(void);
inr_t virt_enable_vtimer_irq(void);
size_t virt_get_irq_count(void);
static const char *virt_get_platform_name(void);
struct {
gicv2_t gicv2;
pl011_uart_t uart;
} virt;
struct arm_machine_ops virt_machine_ops = {
virt_init,
virt_irq_exception,
virt_output_init,
virt_input_init,
virt_enable_vtimer_irq,
virt_get_irq_count,
virt_get_platform_name
};
static void virt_init(void)
{
gicv2_distr_regs_t *distr = (void *) km_map(VIRT_GIC_DISTR_ADDRESS,
ALIGN_UP(sizeof(*distr), PAGE_SIZE), KM_NATURAL_ALIGNMENT,
PAGE_NOT_CACHEABLE | PAGE_READ | PAGE_WRITE | PAGE_KERNEL);
gicv2_cpui_regs_t *cpui = (void *) km_map(VIRT_GIC_CPUI_ADDRESS,
ALIGN_UP(sizeof(*cpui), PAGE_SIZE), KM_NATURAL_ALIGNMENT,
PAGE_NOT_CACHEABLE | PAGE_READ | PAGE_WRITE | PAGE_KERNEL);
gicv2_init(&virt.gicv2, distr, cpui);
}
static void virt_irq_exception(unsigned int exc_no, istate_t *istate)
{
unsigned inum, cpuid;
gicv2_inum_get(&virt.gicv2, &inum, &cpuid);
irq_t *irq = irq_dispatch_and_lock(inum);
if (irq) {
irq->handler(irq);
irq_spinlock_unlock(&irq->lock, false);
} else {
printf("cpu%d: spurious interrupt (inum=%u)\n", CPU->id, inum);
}
gicv2_end(&virt.gicv2, inum, cpuid);
}
static void virt_output_init(void)
{
if (!pl011_uart_init(&virt.uart, VIRT_UART_IRQ, VIRT_UART_ADDRESS))
return;
stdout_wire(&virt.uart.outdev);
}
static void virt_input_init(void)
{
srln_instance_t *srln_instance = srln_init();
if (srln_instance == NULL)
return;
indev_t *sink = stdin_wire();
indev_t *srln = srln_wire(srln_instance, sink);
pl011_uart_input_wire(&virt.uart, srln);
gicv2_enable(&virt.gicv2, VIRT_UART_IRQ);
}
inr_t virt_enable_vtimer_irq(void)
{
gicv2_enable(&virt.gicv2, VIRT_VTIMER_IRQ);
return VIRT_VTIMER_IRQ;
}
size_t virt_get_irq_count(void)
{
return gicv2_inum_get_total(&virt.gicv2);
}
const char *virt_get_platform_name(void)
{
return "arm64virt";
}
HelenOS homepage, sources at GitHub