mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20160330-1' into staging
target-arm queue: * virt: fix the virtual power button by adding a modelled "key press for 100ms" device * various improvements to m25p80 flash devices * implement new QMP query-gic-capability command to let the management layer know what versions of GIC we support # gpg: Signature made Wed 30 Mar 2016 17:30:51 BST using RSA key ID 14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" * remotes/pmaydell/tags/pull-target-arm-20160330-1: arm: implement query-gic-capabilities kvm: add kvm_device_supported() helper function arm: enhance kvm_arm_create_scratch_host_vcpu arm: qmp: add query-gic-capabilities interface block: m25p80: at25128a/at25256a models block: m25p80: n25q256a/n25q512a models block: m25p80: Implemented FSR register block: m25p80: Fast read and 4bytes commands block: m25p80: Dummy cycles for N25Q256/512 block: m25p80: Add configuration registers block: m25p80: 4byte address mode block: m25p80: Extend address mode block: m25p80: Widen flags variable block: m25p80: RESET_ENABLE and RESET_MEMORY commands block: m25p80: Removed unused variable ARM: Virt: Use gpio_key for power button hw/gpio: Add the emulation of gpio_key Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -111,3 +111,4 @@ CONFIG_I82801B11=y
|
||||
CONFIG_ACPI=y
|
||||
CONFIG_SMBIOS=y
|
||||
CONFIG_ASPEED_SOC=y
|
||||
CONFIG_GPIO_KEY=y
|
||||
|
||||
+5
-2
@@ -582,11 +582,11 @@ static void create_rtc(const VirtBoardInfo *vbi, qemu_irq *pic)
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
static DeviceState *pl061_dev;
|
||||
static DeviceState *gpio_key_dev;
|
||||
static void virt_powerdown_req(Notifier *n, void *opaque)
|
||||
{
|
||||
/* use gpio Pin 3 for power button event */
|
||||
qemu_set_irq(qdev_get_gpio_in(pl061_dev, 3), 1);
|
||||
qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1);
|
||||
}
|
||||
|
||||
static Notifier virt_system_powerdown_notifier = {
|
||||
@@ -596,6 +596,7 @@ static Notifier virt_system_powerdown_notifier = {
|
||||
static void create_gpio(const VirtBoardInfo *vbi, qemu_irq *pic)
|
||||
{
|
||||
char *nodename;
|
||||
DeviceState *pl061_dev;
|
||||
hwaddr base = vbi->memmap[VIRT_GPIO].base;
|
||||
hwaddr size = vbi->memmap[VIRT_GPIO].size;
|
||||
int irq = vbi->irqmap[VIRT_GPIO];
|
||||
@@ -618,6 +619,8 @@ static void create_gpio(const VirtBoardInfo *vbi, qemu_irq *pic)
|
||||
qemu_fdt_setprop_string(vbi->fdt, nodename, "clock-names", "apb_pclk");
|
||||
qemu_fdt_setprop_cell(vbi->fdt, nodename, "phandle", phandle);
|
||||
|
||||
gpio_key_dev = sysbus_create_simple("gpio-key", -1,
|
||||
qdev_get_gpio_in(pl061_dev, 3));
|
||||
qemu_fdt_add_subnode(vbi->fdt, "/gpio-keys");
|
||||
qemu_fdt_setprop_string(vbi->fdt, "/gpio-keys", "compatible", "gpio-keys");
|
||||
qemu_fdt_setprop_cell(vbi->fdt, "/gpio-keys", "#size-cells", 0);
|
||||
|
||||
+311
-19
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@ common-obj-$(CONFIG_PL061) += pl061.o
|
||||
common-obj-$(CONFIG_PUV3) += puv3_gpio.o
|
||||
common-obj-$(CONFIG_ZAURUS) += zaurus.o
|
||||
common-obj-$(CONFIG_E500) += mpc8xxx.o
|
||||
common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o
|
||||
|
||||
obj-$(CONFIG_OMAP) += omap_gpio.o
|
||||
obj-$(CONFIG_IMX) += imx_gpio.o
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* GPIO key
|
||||
*
|
||||
* Copyright (c) 2016 Linaro Limited
|
||||
*
|
||||
* Author: Shannon Zhao <shannon.zhao@linaro.org>
|
||||
*
|
||||
* Emulate a (human) keypress -- when the key is triggered by
|
||||
* setting the incoming gpio line, the outbound irq line is
|
||||
* raised for 100ms before being dropped again.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_GPIOKEY "gpio-key"
|
||||
#define GPIOKEY(obj) OBJECT_CHECK(GPIOKEYState, (obj), TYPE_GPIOKEY)
|
||||
#define GPIO_KEY_LATENCY 100 /* 100ms */
|
||||
|
||||
typedef struct GPIOKEYState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
QEMUTimer *timer;
|
||||
qemu_irq irq;
|
||||
} GPIOKEYState;
|
||||
|
||||
static const VMStateDescription vmstate_gpio_key = {
|
||||
.name = "gpio-key",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_TIMER_PTR(timer, GPIOKEYState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void gpio_key_reset(DeviceState *dev)
|
||||
{
|
||||
GPIOKEYState *s = GPIOKEY(dev);
|
||||
|
||||
timer_del(s->timer);
|
||||
}
|
||||
|
||||
static void gpio_key_timer_expired(void *opaque)
|
||||
{
|
||||
GPIOKEYState *s = (GPIOKEYState *)opaque;
|
||||
|
||||
qemu_set_irq(s->irq, 0);
|
||||
timer_del(s->timer);
|
||||
}
|
||||
|
||||
static void gpio_key_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
GPIOKEYState *s = (GPIOKEYState *)opaque;
|
||||
|
||||
qemu_set_irq(s->irq, 1);
|
||||
timer_mod(s->timer,
|
||||
qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + GPIO_KEY_LATENCY);
|
||||
}
|
||||
|
||||
static void gpio_key_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
GPIOKEYState *s = GPIOKEY(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
qdev_init_gpio_in(dev, gpio_key_set_irq, 1);
|
||||
s->timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, gpio_key_timer_expired, s);
|
||||
}
|
||||
|
||||
static void gpio_key_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = gpio_key_realize;
|
||||
dc->vmsd = &vmstate_gpio_key;
|
||||
dc->reset = &gpio_key_reset;
|
||||
}
|
||||
|
||||
static const TypeInfo gpio_key_info = {
|
||||
.name = TYPE_GPIOKEY,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(GPIOKEYState),
|
||||
.class_init = gpio_key_class_init,
|
||||
};
|
||||
|
||||
static void gpio_key_register_types(void)
|
||||
{
|
||||
type_register_static(&gpio_key_info);
|
||||
}
|
||||
|
||||
type_init(gpio_key_register_types)
|
||||
@@ -306,6 +306,15 @@ void kvm_device_access(int fd, int group, uint64_t attr,
|
||||
*/
|
||||
int kvm_create_device(KVMState *s, uint64_t type, bool test);
|
||||
|
||||
/**
|
||||
* kvm_device_supported - probe whether KVM supports specific device
|
||||
*
|
||||
* @vmfd: The fd handler for VM
|
||||
* @type: type of device
|
||||
*
|
||||
* @return: true if supported, otherwise false.
|
||||
*/
|
||||
bool kvm_device_supported(int vmfd, uint64_t type);
|
||||
|
||||
/* Arch specific hooks */
|
||||
|
||||
|
||||
@@ -2339,6 +2339,21 @@ int kvm_create_device(KVMState *s, uint64_t type, bool test)
|
||||
return test ? 0 : create_dev.fd;
|
||||
}
|
||||
|
||||
bool kvm_device_supported(int vmfd, uint64_t type)
|
||||
{
|
||||
struct kvm_create_device create_dev = {
|
||||
.type = type,
|
||||
.fd = -1,
|
||||
.flags = KVM_CREATE_DEVICE_TEST,
|
||||
};
|
||||
|
||||
if (ioctl(vmfd, KVM_CHECK_EXTENSION, KVM_CAP_DEVICE_CTRL) <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (ioctl(vmfd, KVM_CREATE_DEVICE, &create_dev) >= 0);
|
||||
}
|
||||
|
||||
int kvm_set_one_reg(CPUState *cs, uint64_t id, void *source)
|
||||
{
|
||||
struct kvm_one_reg reg;
|
||||
|
||||
@@ -4259,3 +4259,11 @@ void qmp_dump_skeys(const char *filename, Error **errp)
|
||||
error_setg(errp, QERR_FEATURE_DISABLED, "dump-skeys");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_ARM
|
||||
GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_FEATURE_DISABLED, "query-gic-capabilities");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -4134,3 +4134,39 @@
|
||||
##
|
||||
{ 'enum': 'ReplayMode',
|
||||
'data': [ 'none', 'record', 'play' ] }
|
||||
|
||||
##
|
||||
# @GICCapability:
|
||||
#
|
||||
# The struct describes capability for a specific GIC (Generic
|
||||
# Interrupt Controller) version. These bits are not only decided by
|
||||
# QEMU/KVM software version, but also decided by the hardware that
|
||||
# the program is running upon.
|
||||
#
|
||||
# @version: version of GIC to be described. Currently, only 2 and 3
|
||||
# are supported.
|
||||
#
|
||||
# @emulated: whether current QEMU/hardware supports emulated GIC
|
||||
# device in user space.
|
||||
#
|
||||
# @kernel: whether current QEMU/hardware supports hardware
|
||||
# accelerated GIC device in kernel.
|
||||
#
|
||||
# Since: 2.6
|
||||
##
|
||||
{ 'struct': 'GICCapability',
|
||||
'data': { 'version': 'int',
|
||||
'emulated': 'bool',
|
||||
'kernel': 'bool' } }
|
||||
|
||||
##
|
||||
# @query-gic-capabilities:
|
||||
#
|
||||
# This command is ARM-only. It will return a list of GICCapability
|
||||
# objects that describe its capability bits.
|
||||
#
|
||||
# Returns: a list of GICCapability objects.
|
||||
#
|
||||
# Since: 2.6
|
||||
##
|
||||
{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'] }
|
||||
|
||||
@@ -4853,3 +4853,30 @@ Example:
|
||||
{"type": 0, "out-pport": 0, "pport": 0, "vlan-id": 3840,
|
||||
"pop-vlan": 1, "id": 251658240}
|
||||
]}
|
||||
|
||||
EQMP
|
||||
|
||||
#if defined TARGET_ARM
|
||||
{
|
||||
.name = "query-gic-capabilities",
|
||||
.args_type = "",
|
||||
.mhandler.cmd_new = qmp_marshal_query_gic_capabilities,
|
||||
},
|
||||
#endif
|
||||
|
||||
SQMP
|
||||
query-gic-capabilities
|
||||
---------------
|
||||
|
||||
Return a list of GICCapability objects, describing supported GIC
|
||||
(Generic Interrupt Controller) versions.
|
||||
|
||||
Arguments: None
|
||||
|
||||
Example:
|
||||
|
||||
-> { "execute": "query-gic-capabilities" }
|
||||
<- { "return": [{ "version": 2, "emulated": true, "kernel": false },
|
||||
{ "version": 3, "emulated": false, "kernel": true } ] }
|
||||
|
||||
EQMP
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
obj-y += arm-semi.o
|
||||
obj-$(CONFIG_SOFTMMU) += machine.o psci.o arch_dump.o
|
||||
obj-$(CONFIG_SOFTMMU) += machine.o psci.o arch_dump.o monitor.o
|
||||
obj-$(CONFIG_KVM) += kvm.o
|
||||
obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o
|
||||
obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
|
||||
|
||||
+13
-1
@@ -62,13 +62,18 @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!init) {
|
||||
/* Caller doesn't want the VCPU to be initialized, so skip it */
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, init);
|
||||
if (ret >= 0) {
|
||||
ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, init);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
} else if (cpus_to_try) {
|
||||
/* Old kernel which doesn't know about the
|
||||
* PREFERRED_TARGET ioctl: we know it will only support
|
||||
* creating one kind of guest CPU which is its preferred
|
||||
@@ -85,8 +90,15 @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
/* Treat a NULL cpus_to_try argument the same as an empty
|
||||
* list, which means we will fail the call since this must
|
||||
* be an old kernel which doesn't support PREFERRED_TARGET.
|
||||
*/
|
||||
goto err;
|
||||
}
|
||||
|
||||
finish:
|
||||
fdarray[0] = kvmfd;
|
||||
fdarray[1] = vmfd;
|
||||
fdarray[2] = cpufd;
|
||||
|
||||
@@ -124,9 +124,12 @@ void kvm_arm_reset_vcpu(ARMCPU *cpu);
|
||||
* kvm_arm_create_scratch_host_vcpu:
|
||||
* @cpus_to_try: array of QEMU_KVM_ARM_TARGET_* values (terminated with
|
||||
* QEMU_KVM_ARM_TARGET_NONE) to try as fallback if the kernel does not
|
||||
* know the PREFERRED_TARGET ioctl
|
||||
* know the PREFERRED_TARGET ioctl. Passing NULL is the same as passing
|
||||
* an empty array.
|
||||
* @fdarray: filled in with kvmfd, vmfd, cpufd file descriptors in that order
|
||||
* @init: filled in with the necessary values for creating a host vcpu
|
||||
* @init: filled in with the necessary values for creating a host
|
||||
* vcpu. If NULL is provided, will not init the vCPU (though the cpufd
|
||||
* will still be set up).
|
||||
*
|
||||
* Create a scratch vcpu in its own VM of the type preferred by the host
|
||||
* kernel (as would be used for '-cpu host'), for purposes of probing it
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* QEMU monitor.c for ARM.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qmp-commands.h"
|
||||
#include "hw/boards.h"
|
||||
#include "kvm_arm.h"
|
||||
|
||||
static GICCapability *gic_cap_new(int version)
|
||||
{
|
||||
GICCapability *cap = g_new0(GICCapability, 1);
|
||||
cap->version = version;
|
||||
/* by default, support none */
|
||||
cap->emulated = false;
|
||||
cap->kernel = false;
|
||||
return cap;
|
||||
}
|
||||
|
||||
static GICCapabilityList *gic_cap_list_add(GICCapabilityList *head,
|
||||
GICCapability *cap)
|
||||
{
|
||||
GICCapabilityList *item = g_new0(GICCapabilityList, 1);
|
||||
item->value = cap;
|
||||
item->next = head;
|
||||
return item;
|
||||
}
|
||||
|
||||
static inline void gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3)
|
||||
{
|
||||
#ifdef CONFIG_KVM
|
||||
int fdarray[3];
|
||||
|
||||
if (!kvm_arm_create_scratch_host_vcpu(NULL, fdarray, NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test KVM GICv2 */
|
||||
if (kvm_device_supported(fdarray[1], KVM_DEV_TYPE_ARM_VGIC_V2)) {
|
||||
v2->kernel = true;
|
||||
}
|
||||
|
||||
/* Test KVM GICv3 */
|
||||
if (kvm_device_supported(fdarray[1], KVM_DEV_TYPE_ARM_VGIC_V3)) {
|
||||
v3->kernel = true;
|
||||
}
|
||||
|
||||
kvm_arm_destroy_scratch_host_vcpu(fdarray);
|
||||
#endif
|
||||
}
|
||||
|
||||
GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
|
||||
{
|
||||
GICCapabilityList *head = NULL;
|
||||
GICCapability *v2 = gic_cap_new(2), *v3 = gic_cap_new(3);
|
||||
|
||||
v2->emulated = true;
|
||||
/* TODO: we'd change to true after we get emulated GICv3. */
|
||||
v3->emulated = false;
|
||||
|
||||
gic_cap_kvm_probe(v2, v3);
|
||||
|
||||
head = gic_cap_list_add(head, v2);
|
||||
head = gic_cap_list_add(head, v3);
|
||||
|
||||
return head;
|
||||
}
|
||||
Reference in New Issue
Block a user