当前位置:网站首页>QEMU ARM interrupt system architecture
QEMU ARM interrupt system architecture
2022-06-22 05:40:00 【alex_ mianmian】
QEMU interrupt system use GPIO to implement interrupt system. We can understand it by a simple model:
Device.[GPIO_OUT] ->[GPIO_IN].GIC.[GPIO_OUT]->[GPIO_IN].core
GPIO_IN IRQ is created by qdev_init_gpio_in()
GPIO_OUT IRQ is initialized by sysbus_init_irq()->qdev_init_gpio_out_named(). Attention, GPIO_OUT IRQ is not created. Actually it is just a IRQ pointer, and the IRQ pointer will point to the GPIO_IN IRQ which connected. sysbus_connect_irq() connects GPIO_OUT and GPIO_IN IRQ.
Here let's take vexpress-a9 as the example.
ARM core:
ARM core has irq,fiq,virq,vfiq for GPIO_IN IRQ. they are created at:
arm_cpu_initfn()->qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 4);
GIC:
GIC has 96 GPIO_IN IRQs and 4 GPIO_OUT IRQs, and they are created at:
arm_gic_realize()->gic_init_irqs_and_mmio()
void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
const MemoryRegionOps *ops,
const MemoryRegionOps *virt_ops)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
int i = s->num_irq - GIC_INTERNAL;
/* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
* GPIO array layout is thus:
* [0..N-1] SPIs
* [N..N+31] PPIs for CPU 0
* [N+32..N+63] PPIs for CPU 1
* ...
*/
i += (GIC_INTERNAL * s->num_cpu);
qdev_init_gpio_in(DEVICE(s), handler, i); // GPIO_IN IRQs
// GPIO_OUT IRQs
for (i = 0; i < s->num_cpu; i++) {
sysbus_init_irq(sbd, &s->parent_irq[i]);
}
for (i = 0; i < s->num_cpu; i++) {
sysbus_init_irq(sbd, &s->parent_fiq[i]);
}
for (i = 0; i < s->num_cpu; i++) {
sysbus_init_irq(sbd, &s->parent_virq[i]);
}
for (i = 0; i < s->num_cpu; i++) {
sysbus_init_irq(sbd, &s->parent_vfiq[i]);
}
....
}GICState is GIC state logic. We can see it has parent_irq[],parent_fiq[],parent_virq[],parent_vfiq[] 4 GPIO_OUT IRQs.
Actually they are all IRQ pointers. They will point to core's 4 GPIO_IN IRQs. Where do them connect? in init_cpus().
static void init_cpus(MachineState *ms, const char *cpu_type,
const char *privdev, hwaddr periphbase,
qemu_irq *pic, bool secure, bool virt)
{
DeviceState *dev;
SysBusDevice *busdev;
.....
.....
dev = qdev_create(NULL, privdev);
busdev = SYS_BUS_DEVICE(dev); /*here busdev is a9mpcore_priv*/
.....
for (n = 0; n < smp_cpus; n++) {
DeviceState *cpudev = DEVICE(qemu_get_cpu(n));
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
sysbus_connect_irq(busdev, n + smp_cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
sysbus_connect_irq(busdev, n + 2 * smp_cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
sysbus_connect_irq(busdev, n + 3 * smp_cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
}
.....
}sysbus_connect_irq() connect device's GPIO_OUT IRQ to CPU's GPIO_IN IRQ. But here device is a9mpcore_priv, not GIC.
How does it work?
In a9mp_priv_realize(), there is a IRQ pass code:
sysbus_pass_irq(sbd, gicbusdev);
Here sbd presents a9mpcore_priv, gicbusdev presents GIC. This function make them connect, and a9mpcore_priv can use GIC's GPIO_OUT IRQ.
Device:
let's take UART as example.
Device need initialize GPIO_OUT IRQ and connect to GIC GPIO_IN IRQ.
Initialzation at:
static void pl011_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
PL011State *s = PL011(obj);
int i;
.....
for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
sysbus_init_irq(sbd, &s->irq[i]);
printf("alexxie:%s, uart irq at %p\n",__func__,s->irq[i]);
}
.....
}
Connection at:
static void vexpress_common_init(MachineState *machine)
{
qemu_irq pic[64];
pl011_create(map[VE_UART0], pic[5], serial_hd(0));
pl011_create(map[VE_UART1], pic[6], serial_hd(1));
pl011_create(map[VE_UART2], pic[7], serial_hd(2));
pl011_create(map[VE_UART3], pic[8], serial_hd(3));
}map[] is address map of the vexpress. pic[] is the GIC GPIO_IN IRQ.
Let's read pl011_create firstly, then back to pic[].
static inline DeviceState *pl011_create(hwaddr addr,
qemu_irq irq,
Chardev *chr)
{
DeviceState *dev;
SysBusDevice *s;
PL011State *uart_s ;
dev = qdev_create(NULL, "pl011");
s = SYS_BUS_DEVICE(dev);
.....
sysbus_connect_irq(s, 0, irq); //connect irq
uart_s = PL011(dev);
printf("alexdebug:%s, uart irq is at %p,%p,%p,%p,%p,%p\n",__func__,uart_s->irq[0],uart_s->irq[1],uart_s->irq[2],uart_s->irq[3],uart_s->irq[4],uart_s->irq[5]);
return dev;
}Here we can see sysbus_connect_irq() is called to connect pl011 to irq. irq is from pic[5],pic[6],pic[7] and pic[8].
How do we know pic[] is from GIC GPIO_IN? let's check the code.
static void vexpress_common_init(MachineState *machine)
{
VexpressMachineClass *vmc = VEXPRESS_MACHINE_GET_CLASS(machine);
VEDBoardInfo *daughterboard = vmc->daughterboard;
qemu_irq pic[64];
.....
daughterboard->init(vms, machine->ram_size, machine->cpu_type, pic);
.....
}daughterboard->init is a9_daughterboard_init()
static void a9_daughterboard_init(const VexpressMachineState *vms,
ram_addr_t ram_size,
const char *cpu_type,
qemu_irq *pic)
{
/* 0x1e000000 A9MPCore (SCU) private memory region */
init_cpus(machine, cpu_type, TYPE_A9MPCORE_PRIV, 0x1e000000, pic,
vms->secure, vms->virt);
}keep dive into init_cpus()
static void init_cpus(MachineState *ms, const char *cpu_type,
const char *privdev, hwaddr periphbase,
qemu_irq *pic, bool secure, bool virt)
{
DeviceState *dev;
.....
dev = qdev_create(NULL, privdev);
.....
{
a9_s = A9MPCORE_PRIV(dev);
printf("alexdebug:%s, GIC parent_irq at %p\n",__func__,a9_s->gic.parent_irq[0]);
}
for (n = 0; n < 64; n++) {
DeviceState* gicdev=DEVICE(&a9_s->gic);
pic[n] = qdev_get_gpio_in(gicdev, n); //get gic gpio_in
//pic[n] = qdev_get_gpio_in(dev, n);
printf("alexxie:%s, pic[%d] at %p\n",__func__,n,pic[n]);
}
.....
}OK, here we can see pic[] is from GIC by function qdev_get_gpio_in(). You may noticed the code is changed by me. Yes, the origin code pic[] is from a9mpcore_priv and a9mpcore_priv will call GIC. I modified it because I want to try if I can make it simpler to remove one layer of GPIO. it works. So the code is current look.
OK, to here, the question is answered.
边栏推荐
- Kubernetes -- setting up an environment using minicube
- 做事方法:3C 方案设计法
- 2022 Shanxi secondary vocational group "Cyberspace Security" event module b- web page penetration
- [graduation season · advanced technology Er] a graduate student's chatter
- QEMU ARM interrupt system architecture
- 数据的存储(进阶)
- sourcetree报错ssh失败
- Graduation season | a new start, no goodbye
- 2022 Shenzhen Futian District specialized special new small giant enterprise application conditions, with a subsidy of 500000 yuan
- 代码走查的优化方向(接口请求便捷、动态class判断条件过长、去除无用console、抽离公共方法)
猜你喜欢
![P1077 [NOIP2012 普及组] 摆花](/img/0d/f74a2036aa261ed327d9d74291aacc.png)
P1077 [NOIP2012 普及组] 摆花

错误:note: module requires Go 1.17
![Force buckle 33 [search rotation sort array]](/img/0f/d7e2f2fdf48bcd70e6c69bca7d4002.png)
Force buckle 33 [search rotation sort array]

Analysis of 43 cases of MATLAB neural network: Chapter 28 Application Research of decision tree classifier - breast cancer diagnosis

2022 Shanxi secondary vocational group "Cyberspace Security" event module b- web page penetration

Kubernetes - bare metal cluster environment

Remove then add string from variable of Makefile

Talk about MySQL's locking rule "hard hitting MySQL series 15"
![P1077 [noip2012 popularization group] flower display](/img/0d/f74a2036aa261ed327d9d74291aacc.png)
P1077 [noip2012 popularization group] flower display

SCM future employment development direction, learn SCM must know some entry-level knowledge and industry prospects, read the benefit
随机推荐
移动端 realm数据库使用及解耦,跨线程安全使用 OC realm
Analysis of 43 cases of MATLAB neural network: Chapter 29 research on the application of limit learning machine in regression fitting and classification -- Comparative Experiment
Talk about MySQL's locking rule "hard hitting MySQL series 15"
Force buckle 33 [search rotation sort array]
How to find the source of goods for novice stores and how to find high-quality sources of goods?
总有人问我:独立站该怎么玩?3个案例,你看完就懂了
Graduation season | a new start, no goodbye
Research Report on demand and investment opportunities in key areas of global and Chinese strontium tungstate industry 2022-2027
Optimization direction of code walk through (convenient interface requests, long dynamic class judgment conditions, removal of useless consoles, separation of public methods)
\[\e]0;\[email protected]\h: \w\a\]\[\033[01;32m\]\[email protected]\h\[\033[0
SCM future employment development direction, learn SCM must know some entry-level knowledge and industry prospects, read the benefit
关于图片懒加载的实现(总结梳理)
Want to put Facebook ads but don't know where to start? This article takes you to know more about
Does the air valve perform the en 1634-1 fire resistance test for 4 hours?
數據的存儲(進階)
OPTEE notes
毕业季 | 新的开始,不说再见
A piece of code to solve the problem of automatic disconnection of Google colab
Online text code comparison tool
Service migration when deploying SuperMap iserver war package