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-20141223' into staging
target-arm queue: * enable 32-bit EL3 (TrustZone) for vexpress and virt boards * add fw_cfg device to virt board for UEFI firmware config * support passing commandline kernel/initrd to firmware # gpg: Signature made Tue 23 Dec 2014 13:50:33 GMT using RSA key ID 14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" * remotes/pmaydell/tags/pull-target-arm-20141223: (31 commits) hw/arm/virt: enable passing of EFI-stubbed kernel to guest UEFI firmware hw/arm: pass pristine kernel image to guest firmware over fw_cfg hw/loader: split out load_image_gzipped_buffer() arm: add fw_cfg to "virt" board fw_cfg_mem: expose the "data_width" property with fw_cfg_init_mem_wide() fw_cfg_mem: introduce the "data_width" property exec: allows 8-byte accesses in subpage_ops fw_cfg_mem: flip ctl_mem_ops and data_mem_ops to DEVICE_BIG_ENDIAN fw_cfg_mem: max access size and region size are the same for data register fw_cfg: move boards to fw_cfg_init_io() / fw_cfg_init_mem() fw_cfg: hard separation between the MMIO and I/O port mappings target-arm: add cpu feature EL3 to CPUs with Security Extensions target-arm: Disable EL3 on unsupported machines target-arm: Breakout integratorcp and versatilepb cpu init target-arm: Set CPU has_el3 prop during virt init target-arm: Enable CPU has_el3 prop during VE init target-arm: Add arm_boot_info secure_boot control target-arm: Add ARMCPU secure property target-arm: Add feature unset function target-arm: Add virt machine secure property ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -191,9 +191,9 @@ static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp)
|
||||
audio_detach_capture (hw);
|
||||
#endif
|
||||
QLIST_REMOVE (hw, entries);
|
||||
glue (hw->pcm_ops->fini_, TYPE) (hw);
|
||||
glue (s->nb_hw_voices_, TYPE) += 1;
|
||||
glue (audio_pcm_hw_free_resources_ ,TYPE) (hw);
|
||||
glue (hw->pcm_ops->fini_, TYPE) (hw);
|
||||
g_free (hw);
|
||||
*hwp = NULL;
|
||||
}
|
||||
|
||||
@@ -1768,7 +1768,7 @@ static uint64_t subpage_read(void *opaque, hwaddr addr,
|
||||
unsigned len)
|
||||
{
|
||||
subpage_t *subpage = opaque;
|
||||
uint8_t buf[4];
|
||||
uint8_t buf[8];
|
||||
|
||||
#if defined(DEBUG_SUBPAGE)
|
||||
printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__,
|
||||
@@ -1782,6 +1782,8 @@ static uint64_t subpage_read(void *opaque, hwaddr addr,
|
||||
return lduw_p(buf);
|
||||
case 4:
|
||||
return ldl_p(buf);
|
||||
case 8:
|
||||
return ldq_p(buf);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@@ -1791,7 +1793,7 @@ static void subpage_write(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned len)
|
||||
{
|
||||
subpage_t *subpage = opaque;
|
||||
uint8_t buf[4];
|
||||
uint8_t buf[8];
|
||||
|
||||
#if defined(DEBUG_SUBPAGE)
|
||||
printf("%s: subpage %p len %u addr " TARGET_FMT_plx
|
||||
@@ -1808,6 +1810,9 @@ static void subpage_write(void *opaque, hwaddr addr,
|
||||
case 4:
|
||||
stl_p(buf, value);
|
||||
break;
|
||||
case 8:
|
||||
stq_p(buf, value);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@@ -1830,6 +1835,10 @@ static bool subpage_accepts(void *opaque, hwaddr addr,
|
||||
static const MemoryRegionOps subpage_ops = {
|
||||
.read = subpage_read,
|
||||
.write = subpage_write,
|
||||
.impl.min_access_size = 1,
|
||||
.impl.max_access_size = 8,
|
||||
.valid.min_access_size = 1,
|
||||
.valid.max_access_size = 8,
|
||||
.valid.accepts = subpage_accepts,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
+93
-5
@@ -457,6 +457,16 @@ static void do_cpu_reset(void *opaque)
|
||||
env->thumb = info->entry & 1;
|
||||
}
|
||||
} else {
|
||||
/* If we are booting Linux then we need to check whether we are
|
||||
* booting into secure or non-secure state and adjust the state
|
||||
* accordingly. Out of reset, ARM is defined to be in secure state
|
||||
* (SCR.NS = 0), we change that here if non-secure boot has been
|
||||
* requested.
|
||||
*/
|
||||
if (arm_feature(env, ARM_FEATURE_EL3) && !info->secure_boot) {
|
||||
env->cp15.scr_el3 |= SCR_NS;
|
||||
}
|
||||
|
||||
if (CPU(cpu) == first_cpu) {
|
||||
if (env->aarch64) {
|
||||
env->pc = info->loader_start;
|
||||
@@ -478,6 +488,55 @@ static void do_cpu_reset(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* load_image_to_fw_cfg() - Load an image file into an fw_cfg entry identified
|
||||
* by key.
|
||||
* @fw_cfg: The firmware config instance to store the data in.
|
||||
* @size_key: The firmware config key to store the size of the loaded
|
||||
* data under, with fw_cfg_add_i32().
|
||||
* @data_key: The firmware config key to store the loaded data under,
|
||||
* with fw_cfg_add_bytes().
|
||||
* @image_name: The name of the image file to load. If it is NULL, the
|
||||
* function returns without doing anything.
|
||||
* @try_decompress: Whether the image should be decompressed (gunzipped) before
|
||||
* adding it to fw_cfg. If decompression fails, the image is
|
||||
* loaded as-is.
|
||||
*
|
||||
* In case of failure, the function prints an error message to stderr and the
|
||||
* process exits with status 1.
|
||||
*/
|
||||
static void load_image_to_fw_cfg(FWCfgState *fw_cfg, uint16_t size_key,
|
||||
uint16_t data_key, const char *image_name,
|
||||
bool try_decompress)
|
||||
{
|
||||
size_t size = -1;
|
||||
uint8_t *data;
|
||||
|
||||
if (image_name == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (try_decompress) {
|
||||
size = load_image_gzipped_buffer(image_name,
|
||||
LOAD_IMAGE_MAX_GUNZIP_BYTES, &data);
|
||||
}
|
||||
|
||||
if (size == (size_t)-1) {
|
||||
gchar *contents;
|
||||
gsize length;
|
||||
|
||||
if (!g_file_get_contents(image_name, &contents, &length, NULL)) {
|
||||
fprintf(stderr, "failed to load \"%s\"\n", image_name);
|
||||
exit(1);
|
||||
}
|
||||
size = length;
|
||||
data = (uint8_t *)contents;
|
||||
}
|
||||
|
||||
fw_cfg_add_i32(fw_cfg, size_key, size);
|
||||
fw_cfg_add_bytes(fw_cfg, data_key, data, size);
|
||||
}
|
||||
|
||||
void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
|
||||
{
|
||||
CPUState *cs;
|
||||
@@ -500,19 +559,48 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
|
||||
}
|
||||
|
||||
/* Load the kernel. */
|
||||
if (!info->kernel_filename) {
|
||||
if (!info->kernel_filename || info->firmware_loaded) {
|
||||
|
||||
if (have_dtb(info)) {
|
||||
/* If we have a device tree blob, but no kernel to supply it to,
|
||||
* copy it to the base of RAM for a bootloader to pick up.
|
||||
/* If we have a device tree blob, but no kernel to supply it to (or
|
||||
* the kernel is supposed to be loaded by the bootloader), copy the
|
||||
* DTB to the base of RAM for the bootloader to pick up.
|
||||
*/
|
||||
if (load_dtb(info->loader_start, info, 0) < 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* If no kernel specified, do nothing; we will start from address 0
|
||||
* (typically a boot ROM image) in the same way as hardware.
|
||||
if (info->kernel_filename) {
|
||||
FWCfgState *fw_cfg;
|
||||
bool try_decompressing_kernel;
|
||||
|
||||
fw_cfg = fw_cfg_find();
|
||||
try_decompressing_kernel = arm_feature(&cpu->env,
|
||||
ARM_FEATURE_AARCH64);
|
||||
|
||||
/* Expose the kernel, the command line, and the initrd in fw_cfg.
|
||||
* We don't process them here at all, it's all left to the
|
||||
* firmware.
|
||||
*/
|
||||
load_image_to_fw_cfg(fw_cfg,
|
||||
FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
|
||||
info->kernel_filename,
|
||||
try_decompressing_kernel);
|
||||
load_image_to_fw_cfg(fw_cfg,
|
||||
FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
|
||||
info->initrd_filename, false);
|
||||
|
||||
if (info->kernel_cmdline) {
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
|
||||
strlen(info->kernel_cmdline) + 1);
|
||||
fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
|
||||
info->kernel_cmdline);
|
||||
}
|
||||
}
|
||||
|
||||
/* We will start from address 0 (typically a boot ROM image) in the
|
||||
* same way as hardware.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -152,6 +152,17 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
|
||||
Object *cpuobj = object_new(object_class_get_name(cpu_oc));
|
||||
Error *err = NULL;
|
||||
|
||||
/* By default A9 CPUs have EL3 enabled. This board does not currently
|
||||
* support EL3 so the CPU EL3 property is disabled before realization.
|
||||
*/
|
||||
if (object_property_find(cpuobj, "has_el3", NULL)) {
|
||||
object_property_set_bool(cpuobj, false, "has_el3", &err);
|
||||
if (err) {
|
||||
error_report("%s", error_get_pretty(err));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
s->cpu[n] = ARM_CPU(cpuobj);
|
||||
object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
|
||||
"reset-cbar", &error_abort);
|
||||
|
||||
@@ -241,6 +241,18 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
|
||||
cpuobj = object_new(object_class_get_name(oc));
|
||||
cpu = ARM_CPU(cpuobj);
|
||||
|
||||
/* By default A9 and A15 CPUs have EL3 enabled. This board does not
|
||||
* currently support EL3 so the CPU EL3 property is disabled before
|
||||
* realization.
|
||||
*/
|
||||
if (object_property_find(cpuobj, "has_el3", NULL)) {
|
||||
object_property_set_bool(cpuobj, false, "has_el3", &err);
|
||||
if (err) {
|
||||
error_report("%s", error_get_pretty(err));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
|
||||
object_property_set_int(cpuobj, MPCORE_PERIPHBASE,
|
||||
"reset-cbar", &error_abort);
|
||||
|
||||
+29
-2
@@ -15,6 +15,7 @@
|
||||
#include "net/net.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#define TYPE_INTEGRATOR_CM "integrator_core"
|
||||
#define INTEGRATOR_CM(obj) \
|
||||
@@ -469,6 +470,8 @@ static void integratorcp_init(MachineState *machine)
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
ObjectClass *cpu_oc;
|
||||
Object *cpuobj;
|
||||
ARMCPU *cpu;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
@@ -476,16 +479,40 @@ static void integratorcp_init(MachineState *machine)
|
||||
qemu_irq pic[32];
|
||||
DeviceState *dev;
|
||||
int i;
|
||||
Error *err = NULL;
|
||||
|
||||
if (!cpu_model) {
|
||||
cpu_model = "arm926";
|
||||
}
|
||||
cpu = cpu_arm_init(cpu_model);
|
||||
if (!cpu) {
|
||||
|
||||
cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
|
||||
if (!cpu_oc) {
|
||||
fprintf(stderr, "Unable to find CPU definition\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cpuobj = object_new(object_class_get_name(cpu_oc));
|
||||
|
||||
/* By default ARM1176 CPUs have EL3 enabled. This board does not
|
||||
* currently support EL3 so the CPU EL3 property is disabled before
|
||||
* realization.
|
||||
*/
|
||||
if (object_property_find(cpuobj, "has_el3", NULL)) {
|
||||
object_property_set_bool(cpuobj, false, "has_el3", &err);
|
||||
if (err) {
|
||||
error_report("%s", error_get_pretty(err));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
object_property_set_bool(cpuobj, true, "realized", &err);
|
||||
if (err) {
|
||||
error_report("%s", error_get_pretty(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cpu = ARM_CPU(cpuobj);
|
||||
|
||||
memory_region_init_ram(ram, NULL, "integrator.ram", ram_size, &error_abort);
|
||||
vmstate_register_ram_global(ram);
|
||||
/* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash. */
|
||||
|
||||
@@ -101,6 +101,18 @@ static void realview_init(MachineState *machine,
|
||||
Object *cpuobj = object_new(object_class_get_name(cpu_oc));
|
||||
Error *err = NULL;
|
||||
|
||||
/* By default A9,A15 and ARM1176 CPUs have EL3 enabled. This board
|
||||
* does not currently support EL3 so the CPU EL3 property is disabled
|
||||
* before realization.
|
||||
*/
|
||||
if (object_property_find(cpuobj, "has_el3", NULL)) {
|
||||
object_property_set_bool(cpuobj, false, "has_el3", &err);
|
||||
if (err) {
|
||||
error_report("%s", error_get_pretty(err));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_pb && is_mpcore) {
|
||||
object_property_set_int(cpuobj, periphbase, "reset-cbar", &err);
|
||||
if (err) {
|
||||
|
||||
+30
-2
@@ -18,6 +18,7 @@
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/block/flash.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#define VERSATILE_FLASH_ADDR 0x34000000
|
||||
#define VERSATILE_FLASH_SIZE (64 * 1024 * 1024)
|
||||
@@ -175,6 +176,8 @@ static struct arm_boot_info versatile_binfo;
|
||||
|
||||
static void versatile_init(MachineState *machine, int board_id)
|
||||
{
|
||||
ObjectClass *cpu_oc;
|
||||
Object *cpuobj;
|
||||
ARMCPU *cpu;
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
@@ -189,15 +192,40 @@ static void versatile_init(MachineState *machine, int board_id)
|
||||
int n;
|
||||
int done_smc = 0;
|
||||
DriveInfo *dinfo;
|
||||
Error *err = NULL;
|
||||
|
||||
if (!machine->cpu_model) {
|
||||
machine->cpu_model = "arm926";
|
||||
}
|
||||
cpu = cpu_arm_init(machine->cpu_model);
|
||||
if (!cpu) {
|
||||
|
||||
cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, machine->cpu_model);
|
||||
if (!cpu_oc) {
|
||||
fprintf(stderr, "Unable to find CPU definition\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cpuobj = object_new(object_class_get_name(cpu_oc));
|
||||
|
||||
/* By default ARM1176 CPUs have EL3 enabled. This board does not
|
||||
* currently support EL3 so the CPU EL3 property is disabled before
|
||||
* realization.
|
||||
*/
|
||||
if (object_property_find(cpuobj, "has_el3", NULL)) {
|
||||
object_property_set_bool(cpuobj, false, "has_el3", &err);
|
||||
if (err) {
|
||||
error_report("%s", error_get_pretty(err));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
object_property_set_bool(cpuobj, true, "realized", &err);
|
||||
if (err) {
|
||||
error_report("%s", error_get_pretty(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cpu = ARM_CPU(cpuobj);
|
||||
|
||||
memory_region_init_ram(ram, NULL, "versatile.ram", machine->ram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(ram);
|
||||
|
||||
+113
-28
@@ -157,7 +157,27 @@ static hwaddr motherboard_aseries_map[] = {
|
||||
|
||||
typedef struct VEDBoardInfo VEDBoardInfo;
|
||||
|
||||
typedef void DBoardInitFn(const VEDBoardInfo *daughterboard,
|
||||
typedef struct {
|
||||
MachineClass parent;
|
||||
VEDBoardInfo *daughterboard;
|
||||
} VexpressMachineClass;
|
||||
|
||||
typedef struct {
|
||||
MachineState parent;
|
||||
bool secure;
|
||||
} VexpressMachineState;
|
||||
|
||||
#define TYPE_VEXPRESS_MACHINE "vexpress"
|
||||
#define TYPE_VEXPRESS_A9_MACHINE "vexpress-a9"
|
||||
#define TYPE_VEXPRESS_A15_MACHINE "vexpress-a15"
|
||||
#define VEXPRESS_MACHINE(obj) \
|
||||
OBJECT_CHECK(VexpressMachineState, (obj), TYPE_VEXPRESS_MACHINE)
|
||||
#define VEXPRESS_MACHINE_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(VexpressMachineClass, obj, TYPE_VEXPRESS_MACHINE)
|
||||
#define VEXPRESS_MACHINE_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(VexpressMachineClass, klass, TYPE_VEXPRESS_MACHINE)
|
||||
|
||||
typedef void DBoardInitFn(const VexpressMachineState *machine,
|
||||
ram_addr_t ram_size,
|
||||
const char *cpu_model,
|
||||
qemu_irq *pic);
|
||||
@@ -176,7 +196,7 @@ struct VEDBoardInfo {
|
||||
};
|
||||
|
||||
static void init_cpus(const char *cpu_model, const char *privdev,
|
||||
hwaddr periphbase, qemu_irq *pic)
|
||||
hwaddr periphbase, qemu_irq *pic, bool secure)
|
||||
{
|
||||
ObjectClass *cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
|
||||
DeviceState *dev;
|
||||
@@ -193,6 +213,10 @@ static void init_cpus(const char *cpu_model, const char *privdev,
|
||||
Object *cpuobj = object_new(object_class_get_name(cpu_oc));
|
||||
Error *err = NULL;
|
||||
|
||||
if (!secure) {
|
||||
object_property_set_bool(cpuobj, false, "has_el3", NULL);
|
||||
}
|
||||
|
||||
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
|
||||
object_property_set_int(cpuobj, periphbase,
|
||||
"reset-cbar", &error_abort);
|
||||
@@ -232,7 +256,7 @@ static void init_cpus(const char *cpu_model, const char *privdev,
|
||||
}
|
||||
}
|
||||
|
||||
static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
|
||||
static void a9_daughterboard_init(const VexpressMachineState *vms,
|
||||
ram_addr_t ram_size,
|
||||
const char *cpu_model,
|
||||
qemu_irq *pic)
|
||||
@@ -268,7 +292,7 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
|
||||
memory_region_add_subregion(sysmem, 0x60000000, ram);
|
||||
|
||||
/* 0x1e000000 A9MPCore (SCU) private memory region */
|
||||
init_cpus(cpu_model, "a9mpcore_priv", 0x1e000000, pic);
|
||||
init_cpus(cpu_model, "a9mpcore_priv", 0x1e000000, pic, vms->secure);
|
||||
|
||||
/* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
|
||||
|
||||
@@ -322,7 +346,7 @@ static VEDBoardInfo a9_daughterboard = {
|
||||
.init = a9_daughterboard_init,
|
||||
};
|
||||
|
||||
static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
|
||||
static void a15_daughterboard_init(const VexpressMachineState *vms,
|
||||
ram_addr_t ram_size,
|
||||
const char *cpu_model,
|
||||
qemu_irq *pic)
|
||||
@@ -354,7 +378,7 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
|
||||
memory_region_add_subregion(sysmem, 0x80000000, ram);
|
||||
|
||||
/* 0x2c000000 A15MPCore private memory region (GIC) */
|
||||
init_cpus(cpu_model, "a15mpcore_priv", 0x2c000000, pic);
|
||||
init_cpus(cpu_model, "a15mpcore_priv", 0x2c000000, pic, vms->secure);
|
||||
|
||||
/* A15 daughterboard peripherals: */
|
||||
|
||||
@@ -513,9 +537,11 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
|
||||
return OBJECT_CHECK(pflash_t, (dev), "cfi.pflash01");
|
||||
}
|
||||
|
||||
static void vexpress_common_init(VEDBoardInfo *daughterboard,
|
||||
MachineState *machine)
|
||||
static void vexpress_common_init(MachineState *machine)
|
||||
{
|
||||
VexpressMachineState *vms = VEXPRESS_MACHINE(machine);
|
||||
VexpressMachineClass *vmc = VEXPRESS_MACHINE_GET_CLASS(machine);
|
||||
VEDBoardInfo *daughterboard = vmc->daughterboard;;
|
||||
DeviceState *dev, *sysctl, *pl041;
|
||||
qemu_irq pic[64];
|
||||
uint32_t sys_id;
|
||||
@@ -530,8 +556,7 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard,
|
||||
const hwaddr *map = daughterboard->motherboard_map;
|
||||
int i;
|
||||
|
||||
daughterboard->init(daughterboard, machine->ram_size, machine->cpu_model,
|
||||
pic);
|
||||
daughterboard->init(vms, machine->ram_size, machine->cpu_model, pic);
|
||||
|
||||
/*
|
||||
* If a bios file was provided, attempt to map it into memory
|
||||
@@ -678,39 +703,99 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard,
|
||||
daughterboard->bootinfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
|
||||
daughterboard->bootinfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr;
|
||||
daughterboard->bootinfo.modify_dtb = vexpress_modify_dtb;
|
||||
/* Indicate that when booting Linux we should be in secure state */
|
||||
daughterboard->bootinfo.secure_boot = true;
|
||||
arm_load_kernel(ARM_CPU(first_cpu), &daughterboard->bootinfo);
|
||||
}
|
||||
|
||||
static void vexpress_a9_init(MachineState *machine)
|
||||
static bool vexpress_get_secure(Object *obj, Error **errp)
|
||||
{
|
||||
vexpress_common_init(&a9_daughterboard, machine);
|
||||
VexpressMachineState *vms = VEXPRESS_MACHINE(obj);
|
||||
|
||||
return vms->secure;
|
||||
}
|
||||
|
||||
static void vexpress_a15_init(MachineState *machine)
|
||||
static void vexpress_set_secure(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
vexpress_common_init(&a15_daughterboard, machine);
|
||||
VexpressMachineState *vms = VEXPRESS_MACHINE(obj);
|
||||
|
||||
vms->secure = value;
|
||||
}
|
||||
|
||||
static QEMUMachine vexpress_a9_machine = {
|
||||
.name = "vexpress-a9",
|
||||
.desc = "ARM Versatile Express for Cortex-A9",
|
||||
.init = vexpress_a9_init,
|
||||
.block_default_type = IF_SCSI,
|
||||
.max_cpus = 4,
|
||||
static void vexpress_instance_init(Object *obj)
|
||||
{
|
||||
VexpressMachineState *vms = VEXPRESS_MACHINE(obj);
|
||||
|
||||
/* EL3 is enabled by default on vexpress */
|
||||
vms->secure = true;
|
||||
object_property_add_bool(obj, "secure", vexpress_get_secure,
|
||||
vexpress_set_secure, NULL);
|
||||
object_property_set_description(obj, "secure",
|
||||
"Set on/off to enable/disable the ARM "
|
||||
"Security Extensions (TrustZone)",
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void vexpress_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
|
||||
mc->name = TYPE_VEXPRESS_MACHINE;
|
||||
mc->desc = "ARM Versatile Express";
|
||||
mc->init = vexpress_common_init;
|
||||
mc->block_default_type = IF_SCSI;
|
||||
mc->max_cpus = 4;
|
||||
}
|
||||
|
||||
static void vexpress_a9_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
VexpressMachineClass *vmc = VEXPRESS_MACHINE_CLASS(oc);
|
||||
|
||||
mc->name = TYPE_VEXPRESS_A9_MACHINE;
|
||||
mc->desc = "ARM Versatile Express for Cortex-A9";
|
||||
|
||||
vmc->daughterboard = &a9_daughterboard;;
|
||||
}
|
||||
|
||||
static void vexpress_a15_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
VexpressMachineClass *vmc = VEXPRESS_MACHINE_CLASS(oc);
|
||||
|
||||
mc->name = TYPE_VEXPRESS_A15_MACHINE;
|
||||
mc->desc = "ARM Versatile Express for Cortex-A15";
|
||||
|
||||
vmc->daughterboard = &a15_daughterboard;
|
||||
}
|
||||
|
||||
static const TypeInfo vexpress_info = {
|
||||
.name = TYPE_VEXPRESS_MACHINE,
|
||||
.parent = TYPE_MACHINE,
|
||||
.abstract = true,
|
||||
.instance_size = sizeof(VexpressMachineState),
|
||||
.instance_init = vexpress_instance_init,
|
||||
.class_size = sizeof(VexpressMachineClass),
|
||||
.class_init = vexpress_class_init,
|
||||
};
|
||||
|
||||
static QEMUMachine vexpress_a15_machine = {
|
||||
.name = "vexpress-a15",
|
||||
.desc = "ARM Versatile Express for Cortex-A15",
|
||||
.init = vexpress_a15_init,
|
||||
.block_default_type = IF_SCSI,
|
||||
.max_cpus = 4,
|
||||
static const TypeInfo vexpress_a9_info = {
|
||||
.name = TYPE_VEXPRESS_A9_MACHINE,
|
||||
.parent = TYPE_VEXPRESS_MACHINE,
|
||||
.class_init = vexpress_a9_class_init,
|
||||
};
|
||||
|
||||
static const TypeInfo vexpress_a15_info = {
|
||||
.name = TYPE_VEXPRESS_A15_MACHINE,
|
||||
.parent = TYPE_VEXPRESS_MACHINE,
|
||||
.class_init = vexpress_a15_class_init,
|
||||
};
|
||||
|
||||
static void vexpress_machine_init(void)
|
||||
{
|
||||
qemu_register_machine(&vexpress_a9_machine);
|
||||
qemu_register_machine(&vexpress_a15_machine);
|
||||
type_register_static(&vexpress_info);
|
||||
type_register_static(&vexpress_a9_info);
|
||||
type_register_static(&vexpress_a15_info);
|
||||
}
|
||||
|
||||
machine_init(vexpress_machine_init);
|
||||
|
||||
+91
-6
@@ -68,6 +68,7 @@ enum {
|
||||
VIRT_UART,
|
||||
VIRT_MMIO,
|
||||
VIRT_RTC,
|
||||
VIRT_FW_CFG,
|
||||
};
|
||||
|
||||
typedef struct MemMapEntry {
|
||||
@@ -86,6 +87,24 @@ typedef struct VirtBoardInfo {
|
||||
uint32_t clock_phandle;
|
||||
} VirtBoardInfo;
|
||||
|
||||
typedef struct {
|
||||
MachineClass parent;
|
||||
VirtBoardInfo *daughterboard;
|
||||
} VirtMachineClass;
|
||||
|
||||
typedef struct {
|
||||
MachineState parent;
|
||||
bool secure;
|
||||
} VirtMachineState;
|
||||
|
||||
#define TYPE_VIRT_MACHINE "virt"
|
||||
#define VIRT_MACHINE(obj) \
|
||||
OBJECT_CHECK(VirtMachineState, (obj), TYPE_VIRT_MACHINE)
|
||||
#define VIRT_MACHINE_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(VirtMachineClass, obj, TYPE_VIRT_MACHINE)
|
||||
#define VIRT_MACHINE_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE)
|
||||
|
||||
/* Addresses and sizes of our components.
|
||||
* 0..128MB is space for a flash device so we can run bootrom code such as UEFI.
|
||||
* 128MB..256MB is used for miscellaneous device I/O.
|
||||
@@ -107,6 +126,7 @@ static const MemMapEntry a15memmap[] = {
|
||||
[VIRT_GIC_CPU] = { 0x08010000, 0x00010000 },
|
||||
[VIRT_UART] = { 0x09000000, 0x00001000 },
|
||||
[VIRT_RTC] = { 0x09010000, 0x00001000 },
|
||||
[VIRT_FW_CFG] = { 0x09020000, 0x0000000a },
|
||||
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
|
||||
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
|
||||
/* 0x10000000 .. 0x40000000 reserved for PCI */
|
||||
@@ -519,6 +539,23 @@ static void create_flash(const VirtBoardInfo *vbi)
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
static void create_fw_cfg(const VirtBoardInfo *vbi)
|
||||
{
|
||||
hwaddr base = vbi->memmap[VIRT_FW_CFG].base;
|
||||
hwaddr size = vbi->memmap[VIRT_FW_CFG].size;
|
||||
char *nodename;
|
||||
|
||||
fw_cfg_init_mem_wide(base + 8, base, 8);
|
||||
|
||||
nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
|
||||
qemu_fdt_add_subnode(vbi->fdt, nodename);
|
||||
qemu_fdt_setprop_string(vbi->fdt, nodename,
|
||||
"compatible", "qemu,fw-cfg-mmio");
|
||||
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
|
||||
2, base, 2, size);
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
|
||||
{
|
||||
const VirtBoardInfo *board = (const VirtBoardInfo *)binfo;
|
||||
@@ -529,6 +566,7 @@ static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
|
||||
|
||||
static void machvirt_init(MachineState *machine)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(machine);
|
||||
qemu_irq pic[NUM_IRQS];
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
int n;
|
||||
@@ -566,6 +604,10 @@ static void machvirt_init(MachineState *machine)
|
||||
}
|
||||
cpuobj = object_new(object_class_get_name(oc));
|
||||
|
||||
if (!vms->secure) {
|
||||
object_property_set_bool(cpuobj, false, "has_el3", NULL);
|
||||
}
|
||||
|
||||
object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_HVC, "psci-conduit",
|
||||
NULL);
|
||||
|
||||
@@ -604,6 +646,8 @@ static void machvirt_init(MachineState *machine)
|
||||
*/
|
||||
create_virtio_devices(vbi, pic);
|
||||
|
||||
create_fw_cfg(vbi);
|
||||
|
||||
vbi->bootinfo.ram_size = machine->ram_size;
|
||||
vbi->bootinfo.kernel_filename = machine->kernel_filename;
|
||||
vbi->bootinfo.kernel_cmdline = machine->kernel_cmdline;
|
||||
@@ -612,19 +656,60 @@ static void machvirt_init(MachineState *machine)
|
||||
vbi->bootinfo.board_id = -1;
|
||||
vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base;
|
||||
vbi->bootinfo.get_dtb = machvirt_dtb;
|
||||
vbi->bootinfo.firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
|
||||
arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo);
|
||||
}
|
||||
|
||||
static QEMUMachine machvirt_a15_machine = {
|
||||
.name = "virt",
|
||||
.desc = "ARM Virtual Machine",
|
||||
.init = machvirt_init,
|
||||
.max_cpus = 8,
|
||||
static bool virt_get_secure(Object *obj, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
|
||||
return vms->secure;
|
||||
}
|
||||
|
||||
static void virt_set_secure(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
|
||||
vms->secure = value;
|
||||
}
|
||||
|
||||
static void virt_instance_init(Object *obj)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
|
||||
/* EL3 is enabled by default on virt */
|
||||
vms->secure = true;
|
||||
object_property_add_bool(obj, "secure", virt_get_secure,
|
||||
virt_set_secure, NULL);
|
||||
object_property_set_description(obj, "secure",
|
||||
"Set on/off to enable/disable the ARM "
|
||||
"Security Extensions (TrustZone)",
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void virt_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
|
||||
mc->name = TYPE_VIRT_MACHINE;
|
||||
mc->desc = "ARM Virtual Machine",
|
||||
mc->init = machvirt_init;
|
||||
mc->max_cpus = 8;
|
||||
}
|
||||
|
||||
static const TypeInfo machvirt_info = {
|
||||
.name = TYPE_VIRT_MACHINE,
|
||||
.parent = TYPE_MACHINE,
|
||||
.instance_size = sizeof(VirtMachineState),
|
||||
.instance_init = virt_instance_init,
|
||||
.class_size = sizeof(VirtMachineClass),
|
||||
.class_init = virt_class_init,
|
||||
};
|
||||
|
||||
static void machvirt_machine_init(void)
|
||||
{
|
||||
qemu_register_machine(&machvirt_a15_machine);
|
||||
type_register_static(&machvirt_info);
|
||||
}
|
||||
|
||||
machine_init(machvirt_machine_init);
|
||||
|
||||
@@ -126,6 +126,18 @@ static void zynq_init(MachineState *machine)
|
||||
|
||||
cpu = ARM_CPU(object_new(object_class_get_name(cpu_oc)));
|
||||
|
||||
/* By default A9 CPUs have EL3 enabled. This board does not
|
||||
* currently support EL3 so the CPU EL3 property is disabled before
|
||||
* realization.
|
||||
*/
|
||||
if (object_property_find(OBJECT(cpu), "has_el3", NULL)) {
|
||||
object_property_set_bool(OBJECT(cpu), false, "has_el3", &err);
|
||||
if (err) {
|
||||
error_report("%s", error_get_pretty(err));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
object_property_set_int(OBJECT(cpu), ZYNQ_BOARD_MIDR, "midr", &err);
|
||||
if (err) {
|
||||
error_report("%s", error_get_pretty(err));
|
||||
|
||||
+21
-9
@@ -614,14 +614,9 @@ int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
/* This simply prevents g_malloc in the function below from allocating
|
||||
* a huge amount of memory, by placing a limit on the maximum
|
||||
* uncompressed image size that load_image_gzipped will read.
|
||||
*/
|
||||
#define LOAD_IMAGE_MAX_GUNZIP_BYTES (256 << 20)
|
||||
|
||||
/* Load a gzip-compressed kernel. */
|
||||
int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz)
|
||||
/* Load a gzip-compressed kernel to a dynamically allocated buffer. */
|
||||
int load_image_gzipped_buffer(const char *filename, uint64_t max_sz,
|
||||
uint8_t **buffer)
|
||||
{
|
||||
uint8_t *compressed_data = NULL;
|
||||
uint8_t *data = NULL;
|
||||
@@ -653,8 +648,11 @@ int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rom_add_blob_fixed(filename, data, bytes, addr);
|
||||
/* trim to actual size and return to caller */
|
||||
*buffer = g_realloc(data, bytes);
|
||||
ret = bytes;
|
||||
/* ownership has been transferred to caller */
|
||||
data = NULL;
|
||||
|
||||
out:
|
||||
g_free(compressed_data);
|
||||
@@ -662,6 +660,20 @@ int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Load a gzip-compressed kernel. */
|
||||
int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz)
|
||||
{
|
||||
int bytes;
|
||||
uint8_t *data;
|
||||
|
||||
bytes = load_image_gzipped_buffer(filename, max_sz, &data);
|
||||
if (bytes != -1) {
|
||||
rom_add_blob_fixed(filename, data, bytes, addr);
|
||||
g_free(data);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions for reboot-persistent memory regions.
|
||||
* - used for vga bios and option roms.
|
||||
|
||||
@@ -291,48 +291,93 @@ static void machine_initfn(Object *obj)
|
||||
|
||||
object_property_add_str(obj, "accel",
|
||||
machine_get_accel, machine_set_accel, NULL);
|
||||
object_property_set_description(obj, "accel",
|
||||
"Accelerator list",
|
||||
NULL);
|
||||
object_property_add_bool(obj, "kernel-irqchip",
|
||||
machine_get_kernel_irqchip,
|
||||
machine_set_kernel_irqchip,
|
||||
NULL);
|
||||
object_property_set_description(obj, "kernel-irqchip",
|
||||
"Use KVM in-kernel irqchip",
|
||||
NULL);
|
||||
object_property_add(obj, "kvm-shadow-mem", "int",
|
||||
machine_get_kvm_shadow_mem,
|
||||
machine_set_kvm_shadow_mem,
|
||||
NULL, NULL, NULL);
|
||||
object_property_set_description(obj, "kvm-shadow-mem",
|
||||
"KVM shadow MMU size",
|
||||
NULL);
|
||||
object_property_add_str(obj, "kernel",
|
||||
machine_get_kernel, machine_set_kernel, NULL);
|
||||
object_property_set_description(obj, "kernel",
|
||||
"Linux kernel image file",
|
||||
NULL);
|
||||
object_property_add_str(obj, "initrd",
|
||||
machine_get_initrd, machine_set_initrd, NULL);
|
||||
object_property_set_description(obj, "initrd",
|
||||
"Linux initial ramdisk file",
|
||||
NULL);
|
||||
object_property_add_str(obj, "append",
|
||||
machine_get_append, machine_set_append, NULL);
|
||||
object_property_set_description(obj, "append",
|
||||
"Linux kernel command line",
|
||||
NULL);
|
||||
object_property_add_str(obj, "dtb",
|
||||
machine_get_dtb, machine_set_dtb, NULL);
|
||||
object_property_set_description(obj, "dtb",
|
||||
"Linux kernel device tree file",
|
||||
NULL);
|
||||
object_property_add_str(obj, "dumpdtb",
|
||||
machine_get_dumpdtb, machine_set_dumpdtb, NULL);
|
||||
object_property_set_description(obj, "dumpdtb",
|
||||
"Dump current dtb to a file and quit",
|
||||
NULL);
|
||||
object_property_add(obj, "phandle-start", "int",
|
||||
machine_get_phandle_start,
|
||||
machine_set_phandle_start,
|
||||
NULL, NULL, NULL);
|
||||
object_property_set_description(obj, "phandle-start",
|
||||
"The first phandle ID we may generate dynamically",
|
||||
NULL);
|
||||
object_property_add_str(obj, "dt-compatible",
|
||||
machine_get_dt_compatible,
|
||||
machine_set_dt_compatible,
|
||||
NULL);
|
||||
object_property_set_description(obj, "dt-compatible",
|
||||
"Overrides the \"compatible\" property of the dt root node",
|
||||
NULL);
|
||||
object_property_add_bool(obj, "dump-guest-core",
|
||||
machine_get_dump_guest_core,
|
||||
machine_set_dump_guest_core,
|
||||
NULL);
|
||||
object_property_set_description(obj, "dump-guest-core",
|
||||
"Include guest memory in a core dump",
|
||||
NULL);
|
||||
object_property_add_bool(obj, "mem-merge",
|
||||
machine_get_mem_merge,
|
||||
machine_set_mem_merge, NULL);
|
||||
object_property_set_description(obj, "mem-merge",
|
||||
"Enable/disable memory merge support",
|
||||
NULL);
|
||||
object_property_add_bool(obj, "usb",
|
||||
machine_get_usb,
|
||||
machine_set_usb, NULL);
|
||||
object_property_set_description(obj, "usb",
|
||||
"Set on/off to enable/disable usb",
|
||||
NULL);
|
||||
object_property_add_str(obj, "firmware",
|
||||
machine_get_firmware,
|
||||
machine_set_firmware, NULL);
|
||||
object_property_set_description(obj, "firmware",
|
||||
"Firmware image",
|
||||
NULL);
|
||||
object_property_add_bool(obj, "iommu",
|
||||
machine_get_iommu,
|
||||
machine_set_iommu, NULL);
|
||||
object_property_set_description(obj, "iommu",
|
||||
"Set on/off to enable/disable Intel IOMMU (VT-d)",
|
||||
NULL);
|
||||
|
||||
/* Register notifier when init is done for sysbus sanity checks */
|
||||
ms->sysbus_notifier.notify = machine_init_notify;
|
||||
|
||||
+9
-2
@@ -649,7 +649,7 @@ static FWCfgState *bochs_bios_init(void)
|
||||
int i, j;
|
||||
unsigned int apic_id_limit = pc_apic_id_limit(max_cpus);
|
||||
|
||||
fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
|
||||
fw_cfg = fw_cfg_init_io(BIOS_CFG_IOPORT);
|
||||
/* FW_CFG_MAX_CPUS is a bit confusing/problematic on x86:
|
||||
*
|
||||
* SeaBIOS needs FW_CFG_MAX_CPUS for CPU hotplug, but the CPU hotplug
|
||||
@@ -1170,7 +1170,7 @@ FWCfgState *xen_load_linux(const char *kernel_filename,
|
||||
|
||||
assert(kernel_filename != NULL);
|
||||
|
||||
fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
|
||||
fw_cfg = fw_cfg_init_io(BIOS_CFG_IOPORT);
|
||||
rom_set_fw(fw_cfg);
|
||||
|
||||
load_linux(fw_cfg, kernel_filename, initrd_filename,
|
||||
@@ -1805,17 +1805,24 @@ static void pc_machine_initfn(Object *obj)
|
||||
object_property_add(obj, PC_MACHINE_MEMHP_REGION_SIZE, "int",
|
||||
pc_machine_get_hotplug_memory_region_size,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
pcms->max_ram_below_4g = 1ULL << 32; /* 4G */
|
||||
object_property_add(obj, PC_MACHINE_MAX_RAM_BELOW_4G, "size",
|
||||
pc_machine_get_max_ram_below_4g,
|
||||
pc_machine_set_max_ram_below_4g,
|
||||
NULL, NULL, NULL);
|
||||
object_property_set_description(obj, PC_MACHINE_MAX_RAM_BELOW_4G,
|
||||
"Maximum ram below the 4G boundary (32bit boundary)",
|
||||
NULL);
|
||||
|
||||
pcms->vmport = ON_OFF_AUTO_AUTO;
|
||||
object_property_add(obj, PC_MACHINE_VMPORT, "OnOffAuto",
|
||||
pc_machine_get_vmport,
|
||||
pc_machine_set_vmport,
|
||||
NULL, NULL, NULL);
|
||||
object_property_set_description(obj, PC_MACHINE_VMPORT,
|
||||
"Enable vmport (pc & q35)",
|
||||
NULL);
|
||||
|
||||
pcms->enforce_aligned_dimm = true;
|
||||
object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM,
|
||||
|
||||
+190
-62
@@ -31,11 +31,16 @@
|
||||
#include "qemu/config-file.h"
|
||||
|
||||
#define FW_CFG_SIZE 2
|
||||
#define FW_CFG_DATA_SIZE 1
|
||||
#define TYPE_FW_CFG "fw_cfg"
|
||||
#define FW_CFG_NAME "fw_cfg"
|
||||
#define FW_CFG_PATH "/machine/" FW_CFG_NAME
|
||||
#define FW_CFG(obj) OBJECT_CHECK(FWCfgState, (obj), TYPE_FW_CFG)
|
||||
|
||||
#define TYPE_FW_CFG "fw_cfg"
|
||||
#define TYPE_FW_CFG_IO "fw_cfg_io"
|
||||
#define TYPE_FW_CFG_MEM "fw_cfg_mem"
|
||||
|
||||
#define FW_CFG(obj) OBJECT_CHECK(FWCfgState, (obj), TYPE_FW_CFG)
|
||||
#define FW_CFG_IO(obj) OBJECT_CHECK(FWCfgIoState, (obj), TYPE_FW_CFG_IO)
|
||||
#define FW_CFG_MEM(obj) OBJECT_CHECK(FWCfgMemState, (obj), TYPE_FW_CFG_MEM)
|
||||
|
||||
typedef struct FWCfgEntry {
|
||||
uint32_t len;
|
||||
@@ -50,8 +55,6 @@ struct FWCfgState {
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
MemoryRegion ctl_iomem, data_iomem, comb_iomem;
|
||||
uint32_t ctl_iobase, data_iobase;
|
||||
FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
|
||||
FWCfgFiles *files;
|
||||
uint16_t cur_entry;
|
||||
@@ -59,6 +62,25 @@ struct FWCfgState {
|
||||
Notifier machine_ready;
|
||||
};
|
||||
|
||||
struct FWCfgIoState {
|
||||
/*< private >*/
|
||||
FWCfgState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
MemoryRegion comb_iomem;
|
||||
uint32_t iobase;
|
||||
};
|
||||
|
||||
struct FWCfgMemState {
|
||||
/*< private >*/
|
||||
FWCfgState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
MemoryRegion ctl_iomem, data_iomem;
|
||||
uint32_t data_width;
|
||||
MemoryRegionOps wide_data_ops;
|
||||
};
|
||||
|
||||
#define JPG_FILE 0
|
||||
#define BMP_FILE 1
|
||||
|
||||
@@ -264,13 +286,58 @@ static uint8_t fw_cfg_read(FWCfgState *s)
|
||||
static uint64_t fw_cfg_data_mem_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
{
|
||||
return fw_cfg_read(opaque);
|
||||
FWCfgState *s = opaque;
|
||||
uint8_t buf[8];
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
buf[i] = fw_cfg_read(s);
|
||||
}
|
||||
switch (size) {
|
||||
case 1:
|
||||
return buf[0];
|
||||
case 2:
|
||||
return lduw_he_p(buf);
|
||||
case 4:
|
||||
return (uint32_t)ldl_he_p(buf);
|
||||
case 8:
|
||||
return ldq_he_p(buf);
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
static void fw_cfg_data_mem_write(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
fw_cfg_write(opaque, (uint8_t)value);
|
||||
FWCfgState *s = opaque;
|
||||
uint8_t buf[8];
|
||||
unsigned i;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
buf[0] = value;
|
||||
break;
|
||||
case 2:
|
||||
stw_he_p(buf, value);
|
||||
break;
|
||||
case 4:
|
||||
stl_he_p(buf, value);
|
||||
break;
|
||||
case 8:
|
||||
stq_he_p(buf, value);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
for (i = 0; i < size; ++i) {
|
||||
fw_cfg_write(s, buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static bool fw_cfg_data_mem_valid(void *opaque, hwaddr addr,
|
||||
unsigned size, bool is_write)
|
||||
{
|
||||
return addr == 0;
|
||||
}
|
||||
|
||||
static void fw_cfg_ctl_mem_write(void *opaque, hwaddr addr,
|
||||
@@ -312,17 +379,18 @@ static bool fw_cfg_comb_valid(void *opaque, hwaddr addr,
|
||||
|
||||
static const MemoryRegionOps fw_cfg_ctl_mem_ops = {
|
||||
.write = fw_cfg_ctl_mem_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
.valid.accepts = fw_cfg_ctl_mem_valid,
|
||||
};
|
||||
|
||||
static const MemoryRegionOps fw_cfg_data_mem_ops = {
|
||||
.read = fw_cfg_data_mem_read,
|
||||
.write = fw_cfg_data_mem_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 1,
|
||||
.accepts = fw_cfg_data_mem_valid,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -560,19 +628,11 @@ static void fw_cfg_machine_ready(struct Notifier *n, void *data)
|
||||
qemu_register_reset(fw_cfg_machine_reset, s);
|
||||
}
|
||||
|
||||
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
|
||||
hwaddr ctl_addr, hwaddr data_addr)
|
||||
|
||||
|
||||
static void fw_cfg_init1(DeviceState *dev)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *d;
|
||||
FWCfgState *s;
|
||||
|
||||
dev = qdev_create(NULL, TYPE_FW_CFG);
|
||||
qdev_prop_set_uint32(dev, "ctl_iobase", ctl_port);
|
||||
qdev_prop_set_uint32(dev, "data_iobase", data_port);
|
||||
d = SYS_BUS_DEVICE(dev);
|
||||
|
||||
s = FW_CFG(dev);
|
||||
FWCfgState *s = FW_CFG(dev);
|
||||
|
||||
assert(!object_resolve_path(FW_CFG_PATH, NULL));
|
||||
|
||||
@@ -580,12 +640,6 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
|
||||
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
if (ctl_addr) {
|
||||
sysbus_mmio_map(d, 0, ctl_addr);
|
||||
}
|
||||
if (data_addr) {
|
||||
sysbus_mmio_map(d, 1, data_addr);
|
||||
}
|
||||
fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (char *)"QEMU", 4);
|
||||
fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16);
|
||||
fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)(display_type == DT_NOGRAPHIC));
|
||||
@@ -596,48 +650,43 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
|
||||
|
||||
s->machine_ready.notify = fw_cfg_machine_ready;
|
||||
qemu_add_machine_init_done_notifier(&s->machine_ready);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void fw_cfg_initfn(Object *obj)
|
||||
FWCfgState *fw_cfg_init_io(uint32_t iobase)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
FWCfgState *s = FW_CFG(obj);
|
||||
DeviceState *dev;
|
||||
|
||||
memory_region_init_io(&s->ctl_iomem, OBJECT(s), &fw_cfg_ctl_mem_ops, s,
|
||||
"fwcfg.ctl", FW_CFG_SIZE);
|
||||
sysbus_init_mmio(sbd, &s->ctl_iomem);
|
||||
memory_region_init_io(&s->data_iomem, OBJECT(s), &fw_cfg_data_mem_ops, s,
|
||||
"fwcfg.data", FW_CFG_DATA_SIZE);
|
||||
sysbus_init_mmio(sbd, &s->data_iomem);
|
||||
/* In case ctl and data overlap: */
|
||||
memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops, s,
|
||||
"fwcfg", FW_CFG_SIZE);
|
||||
dev = qdev_create(NULL, TYPE_FW_CFG_IO);
|
||||
qdev_prop_set_uint32(dev, "iobase", iobase);
|
||||
fw_cfg_init1(dev);
|
||||
|
||||
return FW_CFG(dev);
|
||||
}
|
||||
|
||||
static void fw_cfg_realize(DeviceState *dev, Error **errp)
|
||||
FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr, hwaddr data_addr,
|
||||
uint32_t data_width)
|
||||
{
|
||||
FWCfgState *s = FW_CFG(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
DeviceState *dev;
|
||||
SysBusDevice *sbd;
|
||||
|
||||
if (s->ctl_iobase + 1 == s->data_iobase) {
|
||||
sysbus_add_io(sbd, s->ctl_iobase, &s->comb_iomem);
|
||||
} else {
|
||||
if (s->ctl_iobase) {
|
||||
sysbus_add_io(sbd, s->ctl_iobase, &s->ctl_iomem);
|
||||
}
|
||||
if (s->data_iobase) {
|
||||
sysbus_add_io(sbd, s->data_iobase, &s->data_iomem);
|
||||
}
|
||||
}
|
||||
dev = qdev_create(NULL, TYPE_FW_CFG_MEM);
|
||||
qdev_prop_set_uint32(dev, "data_width", data_width);
|
||||
|
||||
fw_cfg_init1(dev);
|
||||
|
||||
sbd = SYS_BUS_DEVICE(dev);
|
||||
sysbus_mmio_map(sbd, 0, ctl_addr);
|
||||
sysbus_mmio_map(sbd, 1, data_addr);
|
||||
|
||||
return FW_CFG(dev);
|
||||
}
|
||||
|
||||
FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr)
|
||||
{
|
||||
return fw_cfg_init_mem_wide(ctl_addr, data_addr,
|
||||
fw_cfg_data_mem_ops.valid.max_access_size);
|
||||
}
|
||||
|
||||
static Property fw_cfg_properties[] = {
|
||||
DEFINE_PROP_UINT32("ctl_iobase", FWCfgState, ctl_iobase, -1),
|
||||
DEFINE_PROP_UINT32("data_iobase", FWCfgState, data_iobase, -1),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
FWCfgState *fw_cfg_find(void)
|
||||
{
|
||||
@@ -648,23 +697,102 @@ static void fw_cfg_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = fw_cfg_realize;
|
||||
dc->reset = fw_cfg_reset;
|
||||
dc->vmsd = &vmstate_fw_cfg;
|
||||
dc->props = fw_cfg_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo fw_cfg_info = {
|
||||
.name = TYPE_FW_CFG,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(FWCfgState),
|
||||
.instance_init = fw_cfg_initfn,
|
||||
.class_init = fw_cfg_class_init,
|
||||
};
|
||||
|
||||
|
||||
static Property fw_cfg_io_properties[] = {
|
||||
DEFINE_PROP_UINT32("iobase", FWCfgIoState, iobase, -1),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
FWCfgIoState *s = FW_CFG_IO(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
|
||||
memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops,
|
||||
FW_CFG(s), "fwcfg", FW_CFG_SIZE);
|
||||
sysbus_add_io(sbd, s->iobase, &s->comb_iomem);
|
||||
}
|
||||
|
||||
static void fw_cfg_io_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = fw_cfg_io_realize;
|
||||
dc->props = fw_cfg_io_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo fw_cfg_io_info = {
|
||||
.name = TYPE_FW_CFG_IO,
|
||||
.parent = TYPE_FW_CFG,
|
||||
.instance_size = sizeof(FWCfgIoState),
|
||||
.class_init = fw_cfg_io_class_init,
|
||||
};
|
||||
|
||||
|
||||
static Property fw_cfg_mem_properties[] = {
|
||||
DEFINE_PROP_UINT32("data_width", FWCfgMemState, data_width, -1),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void fw_cfg_mem_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
FWCfgMemState *s = FW_CFG_MEM(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
const MemoryRegionOps *data_ops = &fw_cfg_data_mem_ops;
|
||||
|
||||
memory_region_init_io(&s->ctl_iomem, OBJECT(s), &fw_cfg_ctl_mem_ops,
|
||||
FW_CFG(s), "fwcfg.ctl", FW_CFG_SIZE);
|
||||
sysbus_init_mmio(sbd, &s->ctl_iomem);
|
||||
|
||||
if (s->data_width > data_ops->valid.max_access_size) {
|
||||
/* memberwise copy because the "old_mmio" member is const */
|
||||
s->wide_data_ops.read = data_ops->read;
|
||||
s->wide_data_ops.write = data_ops->write;
|
||||
s->wide_data_ops.endianness = data_ops->endianness;
|
||||
s->wide_data_ops.valid = data_ops->valid;
|
||||
s->wide_data_ops.impl = data_ops->impl;
|
||||
|
||||
s->wide_data_ops.valid.max_access_size = s->data_width;
|
||||
s->wide_data_ops.impl.max_access_size = s->data_width;
|
||||
data_ops = &s->wide_data_ops;
|
||||
}
|
||||
memory_region_init_io(&s->data_iomem, OBJECT(s), data_ops, FW_CFG(s),
|
||||
"fwcfg.data", data_ops->valid.max_access_size);
|
||||
sysbus_init_mmio(sbd, &s->data_iomem);
|
||||
}
|
||||
|
||||
static void fw_cfg_mem_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = fw_cfg_mem_realize;
|
||||
dc->props = fw_cfg_mem_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo fw_cfg_mem_info = {
|
||||
.name = TYPE_FW_CFG_MEM,
|
||||
.parent = TYPE_FW_CFG,
|
||||
.instance_size = sizeof(FWCfgMemState),
|
||||
.class_init = fw_cfg_mem_class_init,
|
||||
};
|
||||
|
||||
|
||||
static void fw_cfg_register_types(void)
|
||||
{
|
||||
type_register_static(&fw_cfg_info);
|
||||
type_register_static(&fw_cfg_io_info);
|
||||
type_register_static(&fw_cfg_mem_info);
|
||||
}
|
||||
|
||||
type_init(fw_cfg_register_types)
|
||||
|
||||
@@ -454,7 +454,7 @@ static void ppc_core99_init(MachineState *machine)
|
||||
pmac_format_nvram_partition(nvr, 0x2000);
|
||||
/* No PCI init: the BIOS will do it */
|
||||
|
||||
fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
|
||||
fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
|
||||
|
||||
@@ -313,7 +313,7 @@ static void ppc_heathrow_init(MachineState *machine)
|
||||
|
||||
/* No PCI init: the BIOS will do it */
|
||||
|
||||
fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
|
||||
fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
|
||||
|
||||
@@ -1655,6 +1655,9 @@ static void spapr_machine_initfn(Object *obj)
|
||||
{
|
||||
object_property_add_str(obj, "kvm-type",
|
||||
spapr_get_kvm_type, spapr_set_kvm_type, NULL);
|
||||
object_property_set_description(obj, "kvm-type",
|
||||
"Specifies the KVM virtualization mode (HV, PR)",
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void ppc_cpu_do_nmi_on_cpu(void *arg)
|
||||
|
||||
+1
-1
@@ -1084,7 +1084,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
|
||||
ecc_init(hwdef->ecc_base, slavio_irq[28],
|
||||
hwdef->ecc_version);
|
||||
|
||||
fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
|
||||
fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
|
||||
|
||||
+1
-1
@@ -892,7 +892,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
|
||||
graphic_width, graphic_height, graphic_depth,
|
||||
(uint8_t *)&nd_table[0].macaddr);
|
||||
|
||||
fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
|
||||
fw_cfg = fw_cfg_init_io(BIOS_CFG_IOPORT);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user