mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-28 14:00:44 +00:00
ppc patch queue 2016-10-06
Currently accumulated target-ppc and spapr machine related patches. - More POWER9 instruction implementations - Additional test case / enabling of test cases for Power - Assorted fixes -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJX9emTAAoJEGw4ysog2bOS1ucP/3ussng8wx5f7ZIM/qNPK1mp kkskXTa14th0mAg5xC0aMZw7svxWjWBbGvB4lTtMMIwtm9jrPdUpNMOMY1E9+Qeb +ZZHw+9abJp41EZP/CVs+5Zdh2VRmuVoc+YvX3nOP+XiLLu13v9pJ4Y/3Nw+kMAR XhGsXvmnf3Pz7ett5d3xGyF4nZI4UkhGi0jCj4y3Tq7Klakq8kjH8EGsCb1uhC0T dVOEI5XNQ+O3TWhhV1Ihssd3TxmmvSp+V6KdzDKtU+NxKdjrtu2lPfe6+sgFK1gy zu6gg4l8tlL2EgGKgnG7oB9M/bzz1Up8BujOW8uOAw3Ci6rL5v2vRnu3g8+sIW1Q 3fYh8a7YjhljFyR13fb45/vXLBzv5ozKSVXozglTYPd8SD4RdBhkXvuSE6U3mjAp p9k0zcv/rc+I86ikif617Jp6nA+3UgOotoGphGohMudlFem6srpp8bYIbh8vJk77 1zIs7ADo6VBeM32cpu95ZXeMRC3ZJBPuHqr/62Bhst0tN1xoRRWMzvQMQkh3ou2a 4IHVOe7hECsFwueiHoHQS1ybaiRQGz6bXSATPCCKg+ERHoqLzh26yyDf/qD4O50R 4t27YrzlGpRa2w+PLhXzo5sJLNwHU6ptCXgZyv31dPAl5lBd493IpORYFUaz5Akq v9ONu7cYu5Lu2fRXJk/X =YUU1 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.8-20161006' into staging ppc patch queue 2016-10-06 Currently accumulated target-ppc and spapr machine related patches. - More POWER9 instruction implementations - Additional test case / enabling of test cases for Power - Assorted fixes # gpg: Signature made Thu 06 Oct 2016 07:05:07 BST # gpg: using RSA key 0x6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" # gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dgibson/tags/ppc-for-2.8-20161006: (29 commits) hw/ppc/spapr: Use POWER8 by default for the pseries-2.8 machine tests/pxe: Use -nodefaults to speed up ppc64/ipv6 pxe test spapr: fix check of cpu alias name in spapr_get_cpu_core_type() tests: enable ohci/uhci/xhci tests on PPC64 libqos: use generic qtest_shutdown() libqos: add PCI management in qtest_vboot()/qtest_shutdown() libqos: add PPC64 PCI support target-ppc: fix vmx instruction type/type2 target-ppc/kvm: Enable transactional memory on POWER8 with KVM-HV, too target-ppc/kvm: Add a wrapper function to check for KVM-PR MAINTAINERS: Add two more ppc related files target-ppc: Implement mtvsrws instruction target-ppc: add vclzlsbb/vctzlsbb instructions target-ppc: add vector compare not equal instructions target-ppc: fix invalid mask - cmpl, bctar target-ppc: add stxvb16x instruction target-ppc: add lxvb16x instruction target-ppc: add stxvh8x instruction target-ppc: add lxvh8x instruction target-ppc: improve stxvw4x implementation ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
e902754e3d
@ -620,6 +620,7 @@ S: Maintained
|
||||
F: hw/ppc/mac_oldworld.c
|
||||
F: hw/pci-host/grackle.c
|
||||
F: hw/misc/macio/
|
||||
F: hw/intc/heathrow_pic.c
|
||||
|
||||
PReP
|
||||
L: qemu-devel@nongnu.org
|
||||
@ -628,6 +629,7 @@ S: Odd Fixes
|
||||
F: hw/ppc/prep.c
|
||||
F: hw/pci-host/prep.[hc]
|
||||
F: hw/isa/pc87312.[hc]
|
||||
F: pc-bios/ppc_rom.bin
|
||||
|
||||
sPAPR
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
|
104
hw/ppc/spapr.c
104
hw/ppc/spapr.c
@ -546,6 +546,51 @@ static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Populate the "ibm,pa-features" property */
|
||||
static void spapr_populate_pa_features(CPUPPCState *env, void *fdt, int offset)
|
||||
{
|
||||
uint8_t pa_features_206[] = { 6, 0,
|
||||
0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 };
|
||||
uint8_t pa_features_207[] = { 24, 0,
|
||||
0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0,
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
|
||||
0x80, 0x00, 0x80, 0x00, 0x00, 0x00 };
|
||||
uint8_t *pa_features;
|
||||
size_t pa_size;
|
||||
|
||||
switch (env->mmu_model) {
|
||||
case POWERPC_MMU_2_06:
|
||||
case POWERPC_MMU_2_06a:
|
||||
pa_features = pa_features_206;
|
||||
pa_size = sizeof(pa_features_206);
|
||||
break;
|
||||
case POWERPC_MMU_2_07:
|
||||
case POWERPC_MMU_2_07a:
|
||||
pa_features = pa_features_207;
|
||||
pa_size = sizeof(pa_features_207);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (env->ci_large_pages) {
|
||||
/*
|
||||
* Note: we keep CI large pages off by default because a 64K capable
|
||||
* guest provisioned with large pages might otherwise try to map a qemu
|
||||
* framebuffer (or other kind of memory mapped PCI BAR) using 64K pages
|
||||
* even if that qemu runs on a 4k host.
|
||||
* We dd this bit back here if we are confident this is not an issue
|
||||
*/
|
||||
pa_features[3] |= 0x20;
|
||||
}
|
||||
if (kvmppc_has_cap_htm() && pa_size > 24) {
|
||||
pa_features[24] |= 0x80; /* Transactional memory support */
|
||||
}
|
||||
|
||||
_FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size)));
|
||||
}
|
||||
|
||||
static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
|
||||
sPAPRMachineState *spapr)
|
||||
{
|
||||
@ -573,24 +618,6 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index)));
|
||||
}
|
||||
|
||||
/* Note: we keep CI large pages off for now because a 64K capable guest
|
||||
* provisioned with large pages might otherwise try to map a qemu
|
||||
* framebuffer (or other kind of memory mapped PCI BAR) using 64K pages
|
||||
* even if that qemu runs on a 4k host.
|
||||
*
|
||||
* We can later add this bit back when we are confident this is not
|
||||
* an issue (!HV KVM or 64K host)
|
||||
*/
|
||||
uint8_t pa_features_206[] = { 6, 0,
|
||||
0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 };
|
||||
uint8_t pa_features_207[] = { 24, 0,
|
||||
0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0,
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
|
||||
0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
|
||||
uint8_t *pa_features;
|
||||
size_t pa_size;
|
||||
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "reg", index)));
|
||||
_FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
|
||||
|
||||
@ -657,18 +684,7 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
|
||||
page_sizes_prop, page_sizes_prop_size)));
|
||||
}
|
||||
|
||||
/* Do the ibm,pa-features property, adjust it for ci-large-pages */
|
||||
if (env->mmu_model == POWERPC_MMU_2_06) {
|
||||
pa_features = pa_features_206;
|
||||
pa_size = sizeof(pa_features_206);
|
||||
} else /* env->mmu_model == POWERPC_MMU_2_07 */ {
|
||||
pa_features = pa_features_207;
|
||||
pa_size = sizeof(pa_features_207);
|
||||
}
|
||||
if (env->ci_large_pages) {
|
||||
pa_features[3] |= 0x20;
|
||||
}
|
||||
_FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size)));
|
||||
spapr_populate_pa_features(env, fdt, offset);
|
||||
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id",
|
||||
cs->cpu_index / vcpus_per_socket)));
|
||||
@ -1759,7 +1775,7 @@ static void ppc_spapr_init(MachineState *machine)
|
||||
|
||||
/* init CPUs */
|
||||
if (machine->cpu_model == NULL) {
|
||||
machine->cpu_model = kvm_enabled() ? "host" : "POWER7";
|
||||
machine->cpu_model = kvm_enabled() ? "host" : smc->tcg_default_cpu;
|
||||
}
|
||||
|
||||
ppc_cpu_parse_features(machine->cpu_model);
|
||||
@ -2386,6 +2402,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id;
|
||||
|
||||
smc->dr_lmb_enabled = true;
|
||||
smc->tcg_default_cpu = "POWER8";
|
||||
mc->query_hotpluggable_cpus = spapr_query_hotpluggable_cpus;
|
||||
fwc->get_dev_path = spapr_get_fw_dev_path;
|
||||
nc->nmi_monitor_handler = spapr_nmi;
|
||||
@ -2436,19 +2453,40 @@ static const TypeInfo spapr_machine_info = {
|
||||
} \
|
||||
type_init(spapr_machine_register_##suffix)
|
||||
|
||||
/*
|
||||
* pseries-2.8
|
||||
*/
|
||||
static void spapr_machine_2_8_instance_options(MachineState *machine)
|
||||
{
|
||||
}
|
||||
|
||||
static void spapr_machine_2_8_class_options(MachineClass *mc)
|
||||
{
|
||||
/* Defaults for the latest behaviour inherited from the base class */
|
||||
}
|
||||
|
||||
DEFINE_SPAPR_MACHINE(2_8, "2.8", true);
|
||||
|
||||
/*
|
||||
* pseries-2.7
|
||||
*/
|
||||
#define SPAPR_COMPAT_2_7 \
|
||||
HW_COMPAT_2_7 \
|
||||
|
||||
static void spapr_machine_2_7_instance_options(MachineState *machine)
|
||||
{
|
||||
}
|
||||
|
||||
static void spapr_machine_2_7_class_options(MachineClass *mc)
|
||||
{
|
||||
/* Defaults for the latest behaviour inherited from the base class */
|
||||
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||
|
||||
spapr_machine_2_8_class_options(mc);
|
||||
smc->tcg_default_cpu = "POWER7";
|
||||
SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_7);
|
||||
}
|
||||
|
||||
DEFINE_SPAPR_MACHINE(2_7, "2.7", true);
|
||||
DEFINE_SPAPR_MACHINE(2_7, "2.7", false);
|
||||
|
||||
/*
|
||||
* pseries-2.6
|
||||
|
@ -92,20 +92,20 @@ char *spapr_get_cpu_core_type(const char *model)
|
||||
gchar **model_pieces = g_strsplit(model, ",", 2);
|
||||
|
||||
core_type = g_strdup_printf("%s-%s", model_pieces[0], TYPE_SPAPR_CPU_CORE);
|
||||
g_strfreev(model_pieces);
|
||||
|
||||
/* Check whether it exists or whether we have to look up an alias name */
|
||||
if (!object_class_by_name(core_type)) {
|
||||
const char *realmodel;
|
||||
|
||||
g_free(core_type);
|
||||
realmodel = ppc_cpu_lookup_alias(model);
|
||||
core_type = NULL;
|
||||
realmodel = ppc_cpu_lookup_alias(model_pieces[0]);
|
||||
if (realmodel) {
|
||||
return spapr_get_cpu_core_type(realmodel);
|
||||
core_type = spapr_get_cpu_core_type(realmodel);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_strfreev(model_pieces);
|
||||
return core_type;
|
||||
}
|
||||
|
||||
|
@ -658,7 +658,7 @@ static void vscsi_process_login(VSCSIState *s, vscsi_req *req)
|
||||
struct srp_login_rsp *rsp = &iu->srp.login_rsp;
|
||||
uint64_t tag = iu->srp.rsp.tag;
|
||||
|
||||
trace_spapr_vscsi__process_login();
|
||||
trace_spapr_vscsi_process_login();
|
||||
|
||||
/* TODO handle case that requested size is wrong and
|
||||
* buffer format is wrong
|
||||
|
@ -225,7 +225,7 @@ spapr_vscsi_command_complete_sense_data2(unsigned s8, unsigned s9, unsigned s10,
|
||||
spapr_vscsi_command_complete_status(uint32_t status) "Command complete err=%"PRIu32
|
||||
spapr_vscsi_save_request(uint32_t qtag, unsigned desc, unsigned offset) "saving tag=%"PRIu32", current desc#%u, offset=0x%x"
|
||||
spapr_vscsi_load_request(uint32_t qtag, unsigned desc, unsigned offset) "restoring tag=%"PRIu32", current desc#%u, offset=0x%x"
|
||||
spapr_vscsi__process_login(void) "Got login, sending response !"
|
||||
spapr_vscsi_process_login(void) "Got login, sending response !"
|
||||
spapr_vscsi_queue_cmd_no_drive(uint64_t lun) "Command for lun %08" PRIx64 " with no drive"
|
||||
spapr_vscsi_queue_cmd(uint32_t qtag, unsigned cdb, const char *cmd, int lun, int ret) "Queued command tag 0x%"PRIx32" CMD 0x%x=%s LUN %d ret: %d"
|
||||
spapr_vscsi_do_crq(unsigned c0, unsigned c1) "crq: %02x %02x ..."
|
||||
|
@ -39,6 +39,7 @@ struct sPAPRMachineClass {
|
||||
/*< public >*/
|
||||
bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */
|
||||
bool use_ohci_by_default; /* use USB-OHCI instead of XHCI */
|
||||
const char *tcg_default_cpu; /* which (TCG) CPU to simulate by default */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -147,6 +147,9 @@ DEF_HELPER_4(vcmpequb, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpequh, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpequw, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpequd, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpneb, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpneh, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpnew, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpnezb, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpnezh, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpnezw, void, env, avr, avr, avr)
|
||||
@ -166,6 +169,9 @@ DEF_HELPER_4(vcmpequb_dot, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpequh_dot, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpequw_dot, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpequd_dot, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpneb_dot, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpneh_dot, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpnew_dot, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpnezb_dot, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpnezh_dot, void, env, avr, avr, avr)
|
||||
DEF_HELPER_4(vcmpnezw_dot, void, env, avr, avr, avr)
|
||||
@ -337,6 +343,8 @@ DEF_HELPER_2(vpopcntb, void, avr, avr)
|
||||
DEF_HELPER_2(vpopcnth, void, avr, avr)
|
||||
DEF_HELPER_2(vpopcntw, void, avr, avr)
|
||||
DEF_HELPER_2(vpopcntd, void, avr, avr)
|
||||
DEF_HELPER_1(vclzlsbb, tl, avr)
|
||||
DEF_HELPER_1(vctzlsbb, tl, avr)
|
||||
DEF_HELPER_3(vbpermd, void, avr, avr, avr)
|
||||
DEF_HELPER_3(vbpermq, void, avr, avr, avr)
|
||||
DEF_HELPER_2(vgbbd, void, avr, avr)
|
||||
|
@ -735,20 +735,24 @@ VCMP(gtsd, >, s64)
|
||||
#undef VCMP_DO
|
||||
#undef VCMP
|
||||
|
||||
#define VCMPNEZ_DO(suffix, element, etype, record) \
|
||||
void helper_vcmpnez##suffix(CPUPPCState *env, ppc_avr_t *r, \
|
||||
#define VCMPNE_DO(suffix, element, etype, cmpzero, record) \
|
||||
void helper_vcmpne##suffix(CPUPPCState *env, ppc_avr_t *r, \
|
||||
ppc_avr_t *a, ppc_avr_t *b) \
|
||||
{ \
|
||||
etype ones = (etype)-1; \
|
||||
etype all = ones; \
|
||||
etype none = 0; \
|
||||
etype result, none = 0; \
|
||||
int i; \
|
||||
\
|
||||
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
|
||||
etype result = ((a->element[i] == 0) \
|
||||
if (cmpzero) { \
|
||||
result = ((a->element[i] == 0) \
|
||||
|| (b->element[i] == 0) \
|
||||
|| (a->element[i] != b->element[i]) ? \
|
||||
ones : 0x0); \
|
||||
} else { \
|
||||
result = (a->element[i] != b->element[i]) ? ones : 0x0; \
|
||||
} \
|
||||
r->element[i] = result; \
|
||||
all &= result; \
|
||||
none |= result; \
|
||||
@ -762,14 +766,17 @@ void helper_vcmpnez##suffix(CPUPPCState *env, ppc_avr_t *r, \
|
||||
* suffix - instruction mnemonic suffix (b: byte, h: halfword, w: word)
|
||||
* element - element type to access from vector
|
||||
*/
|
||||
#define VCMPNEZ(suffix, element, etype) \
|
||||
VCMPNEZ_DO(suffix, element, etype, 0) \
|
||||
VCMPNEZ_DO(suffix##_dot, element, etype, 1)
|
||||
VCMPNEZ(b, u8, uint8_t)
|
||||
VCMPNEZ(h, u16, uint16_t)
|
||||
VCMPNEZ(w, u32, uint32_t)
|
||||
#undef VCMPNEZ_DO
|
||||
#undef VCMPNEZ
|
||||
#define VCMPNE(suffix, element, etype, cmpzero) \
|
||||
VCMPNE_DO(suffix, element, etype, cmpzero, 0) \
|
||||
VCMPNE_DO(suffix##_dot, element, etype, cmpzero, 1)
|
||||
VCMPNE(zb, u8, uint8_t, 1)
|
||||
VCMPNE(zh, u16, uint16_t, 1)
|
||||
VCMPNE(zw, u32, uint32_t, 1)
|
||||
VCMPNE(b, u8, uint8_t, 0)
|
||||
VCMPNE(h, u16, uint16_t, 0)
|
||||
VCMPNE(w, u32, uint32_t, 0)
|
||||
#undef VCMPNE_DO
|
||||
#undef VCMPNE
|
||||
|
||||
#define VCMPFP_DO(suffix, compare, order, record) \
|
||||
void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r, \
|
||||
@ -874,6 +881,36 @@ VCT(uxs, cvtsduw, u32)
|
||||
VCT(sxs, cvtsdsw, s32)
|
||||
#undef VCT
|
||||
|
||||
target_ulong helper_vclzlsbb(ppc_avr_t *r)
|
||||
{
|
||||
target_ulong count = 0;
|
||||
int i;
|
||||
VECTOR_FOR_INORDER_I(i, u8) {
|
||||
if (r->u8[i] & 0x01) {
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
target_ulong helper_vctzlsbb(ppc_avr_t *r)
|
||||
{
|
||||
target_ulong count = 0;
|
||||
int i;
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) {
|
||||
#else
|
||||
for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
|
||||
#endif
|
||||
if (r->u8[i] & 0x01) {
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
|
||||
ppc_avr_t *b, ppc_avr_t *c)
|
||||
{
|
||||
|
@ -80,6 +80,7 @@ static int cap_ppc_watchdog;
|
||||
static int cap_papr;
|
||||
static int cap_htab_fd;
|
||||
static int cap_fixup_hcalls;
|
||||
static int cap_htm; /* Hardware transactional memory support */
|
||||
|
||||
static uint32_t debug_inst_opcode;
|
||||
|
||||
@ -101,6 +102,16 @@ static void kvm_kick_cpu(void *opaque)
|
||||
qemu_cpu_kick(CPU(cpu));
|
||||
}
|
||||
|
||||
/* Check whether we are running with KVM-PR (instead of KVM-HV). This
|
||||
* should only be used for fallback tests - generally we should use
|
||||
* explicit capabilities for the features we want, rather than
|
||||
* assuming what is/isn't available depending on the KVM variant. */
|
||||
static bool kvmppc_is_pr(KVMState *ks)
|
||||
{
|
||||
/* Assume KVM-PR if the GET_PVINFO capability is available */
|
||||
return kvm_check_extension(ks, KVM_CAP_PPC_GET_PVINFO) != 0;
|
||||
}
|
||||
|
||||
static int kvm_ppc_register_host_cpu_type(void);
|
||||
|
||||
int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
@ -122,6 +133,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
* only activated after this by kvmppc_set_papr() */
|
||||
cap_htab_fd = kvm_check_extension(s, KVM_CAP_PPC_HTAB_FD);
|
||||
cap_fixup_hcalls = kvm_check_extension(s, KVM_CAP_PPC_FIXUP_HCALL);
|
||||
cap_htm = kvm_vm_check_extension(s, KVM_CAP_PPC_HTM);
|
||||
|
||||
if (!cap_interrupt_level) {
|
||||
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
|
||||
@ -221,10 +233,9 @@ static void kvm_get_fallback_smmu_info(PowerPCCPU *cpu,
|
||||
*
|
||||
* For that to work we make a few assumptions:
|
||||
*
|
||||
* - If KVM_CAP_PPC_GET_PVINFO is supported we are running "PR"
|
||||
* KVM which only supports 4K and 16M pages, but supports them
|
||||
* regardless of the backing store characteritics. We also don't
|
||||
* support 1T segments.
|
||||
* - Check whether we are running "PR" KVM which only supports 4K
|
||||
* and 16M pages, but supports them regardless of the backing
|
||||
* store characteritics. We also don't support 1T segments.
|
||||
*
|
||||
* This is safe as if HV KVM ever supports that capability or PR
|
||||
* KVM grows supports for more page/segment sizes, those versions
|
||||
@ -239,7 +250,7 @@ static void kvm_get_fallback_smmu_info(PowerPCCPU *cpu,
|
||||
* implements KVM_CAP_PPC_GET_SMMU_INFO and thus doesn't hit
|
||||
* this fallback.
|
||||
*/
|
||||
if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO)) {
|
||||
if (kvmppc_is_pr(cs->kvm_state)) {
|
||||
/* No flags */
|
||||
info->flags = 0;
|
||||
info->slb_size = 64;
|
||||
@ -559,11 +570,18 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
|
||||
idle_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, kvm_kick_cpu, cpu);
|
||||
|
||||
/* Some targets support access to KVM's guest TLB. */
|
||||
switch (cenv->mmu_model) {
|
||||
case POWERPC_MMU_BOOKE206:
|
||||
/* This target supports access to KVM's guest TLB */
|
||||
ret = kvm_booke206_tlb_init(cpu);
|
||||
break;
|
||||
case POWERPC_MMU_2_07:
|
||||
if (!cap_htm && !kvmppc_is_pr(cs->kvm_state)) {
|
||||
/* KVM-HV has transactional memory on POWER8 also without the
|
||||
* KVM_CAP_PPC_HTM extension, so enable it here instead. */
|
||||
cap_htm = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2268,11 +2286,8 @@ int kvmppc_reset_htab(int shift_hint)
|
||||
|
||||
/* We have a kernel that predates the htab reset calls. For PR
|
||||
* KVM, we need to allocate the htab ourselves, for an HV KVM of
|
||||
* this era, it has allocated a 16MB fixed size hash table
|
||||
* already. Kernels of this era have the GET_PVINFO capability
|
||||
* only on PR, so we use this hack to determine the right
|
||||
* answer */
|
||||
if (kvm_check_extension(kvm_state, KVM_CAP_PPC_GET_PVINFO)) {
|
||||
* this era, it has allocated a 16MB fixed size hash table already. */
|
||||
if (kvmppc_is_pr(kvm_state)) {
|
||||
/* PR - tell caller to allocate htab */
|
||||
return 0;
|
||||
} else {
|
||||
@ -2353,6 +2368,11 @@ bool kvmppc_has_cap_fixup_hcalls(void)
|
||||
return cap_fixup_hcalls;
|
||||
}
|
||||
|
||||
bool kvmppc_has_cap_htm(void)
|
||||
{
|
||||
return cap_htm;
|
||||
}
|
||||
|
||||
static PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc)
|
||||
{
|
||||
ObjectClass *oc = OBJECT_CLASS(pcc);
|
||||
|
@ -55,6 +55,7 @@ void kvmppc_hash64_free_pteg(uint64_t token);
|
||||
void kvmppc_hash64_write_pte(CPUPPCState *env, target_ulong pte_index,
|
||||
target_ulong pte0, target_ulong pte1);
|
||||
bool kvmppc_has_cap_fixup_hcalls(void);
|
||||
bool kvmppc_has_cap_htm(void);
|
||||
int kvmppc_enable_hwrng(void);
|
||||
int kvmppc_put_books_sregs(PowerPCCPU *cpu);
|
||||
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
|
||||
@ -249,6 +250,11 @@ static inline bool kvmppc_has_cap_fixup_hcalls(void)
|
||||
abort();
|
||||
}
|
||||
|
||||
static inline bool kvmppc_has_cap_htm(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int kvmppc_enable_hwrng(void)
|
||||
{
|
||||
return -1;
|
||||
|
@ -6203,7 +6203,7 @@ static opcode_t opcodes[] = {
|
||||
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
|
||||
GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
|
||||
GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
|
||||
GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER),
|
||||
GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400001, PPC_INTEGER),
|
||||
GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
|
||||
#if defined(TARGET_PPC64)
|
||||
GEN_HANDLER_E(cmpeqb, 0x1F, 0x00, 0x07, 0x00600000, PPC_NONE, PPC2_ISA300),
|
||||
@ -6297,7 +6297,7 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
|
||||
GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
|
||||
GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
|
||||
GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
|
||||
GEN_HANDLER_E(bctar, 0x13, 0x10, 0x11, 0, PPC_NONE, PPC2_BCTAR_ISA207),
|
||||
GEN_HANDLER_E(bctar, 0x13, 0x10, 0x11, 0x0000E000, PPC_NONE, PPC2_BCTAR_ISA207),
|
||||
GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
|
||||
GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
|
||||
#if defined(TARGET_PPC64)
|
||||
|
@ -510,7 +510,16 @@ GEN_VXRFORM(vcmpeqfp, 3, 3)
|
||||
GEN_VXRFORM(vcmpgefp, 3, 7)
|
||||
GEN_VXRFORM(vcmpgtfp, 3, 11)
|
||||
GEN_VXRFORM(vcmpbfp, 3, 15)
|
||||
GEN_VXRFORM(vcmpneb, 3, 0)
|
||||
GEN_VXRFORM(vcmpneh, 3, 1)
|
||||
GEN_VXRFORM(vcmpnew, 3, 2)
|
||||
|
||||
GEN_VXRFORM_DUAL(vcmpequb, PPC_ALTIVEC, PPC_NONE, \
|
||||
vcmpneb, PPC_NONE, PPC2_ISA300)
|
||||
GEN_VXRFORM_DUAL(vcmpequh, PPC_ALTIVEC, PPC_NONE, \
|
||||
vcmpneh, PPC_NONE, PPC2_ISA300)
|
||||
GEN_VXRFORM_DUAL(vcmpequw, PPC_ALTIVEC, PPC_NONE, \
|
||||
vcmpnew, PPC_NONE, PPC2_ISA300)
|
||||
GEN_VXRFORM_DUAL(vcmpeqfp, PPC_ALTIVEC, PPC_NONE, \
|
||||
vcmpequd, PPC_NONE, PPC2_ALTIVEC_207)
|
||||
GEN_VXRFORM_DUAL(vcmpbfp, PPC_ALTIVEC, PPC_NONE, \
|
||||
@ -584,6 +593,18 @@ static void glue(gen_, name)(DisasContext *ctx) \
|
||||
tcg_temp_free_ptr(rd); \
|
||||
}
|
||||
|
||||
#define GEN_VXFORM_NOA_3(name, opc2, opc3, opc4) \
|
||||
static void glue(gen_, name)(DisasContext *ctx) \
|
||||
{ \
|
||||
TCGv_ptr rb; \
|
||||
if (unlikely(!ctx->altivec_enabled)) { \
|
||||
gen_exception(ctx, POWERPC_EXCP_VPU); \
|
||||
return; \
|
||||
} \
|
||||
rb = gen_avr_ptr(rB(ctx->opcode)); \
|
||||
gen_helper_##name(cpu_gpr[rD(ctx->opcode)], rb); \
|
||||
tcg_temp_free_ptr(rb); \
|
||||
}
|
||||
GEN_VXFORM_NOA(vupkhsb, 7, 8);
|
||||
GEN_VXFORM_NOA(vupkhsh, 7, 9);
|
||||
GEN_VXFORM_NOA(vupkhsw, 7, 25);
|
||||
@ -691,18 +712,18 @@ GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
|
||||
GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
|
||||
GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
|
||||
GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15);
|
||||
GEN_VXFORM_DUAL(vspltb, PPC_NONE, PPC2_ALTIVEC_207,
|
||||
vextractub, PPC_NONE, PPC2_ISA300);
|
||||
GEN_VXFORM_DUAL(vsplth, PPC_NONE, PPC2_ALTIVEC_207,
|
||||
vextractuh, PPC_NONE, PPC2_ISA300);
|
||||
GEN_VXFORM_DUAL(vspltw, PPC_NONE, PPC2_ALTIVEC_207,
|
||||
vextractuw, PPC_NONE, PPC2_ISA300);
|
||||
GEN_VXFORM_DUAL(vspltisb, PPC_NONE, PPC2_ALTIVEC_207,
|
||||
vinsertb, PPC_NONE, PPC2_ISA300);
|
||||
GEN_VXFORM_DUAL(vspltish, PPC_NONE, PPC2_ALTIVEC_207,
|
||||
vinserth, PPC_NONE, PPC2_ISA300);
|
||||
GEN_VXFORM_DUAL(vspltisw, PPC_NONE, PPC2_ALTIVEC_207,
|
||||
vinsertw, PPC_NONE, PPC2_ISA300);
|
||||
GEN_VXFORM_DUAL(vspltb, PPC_ALTIVEC, PPC_NONE,
|
||||
vextractub, PPC_NONE, PPC2_ISA300);
|
||||
GEN_VXFORM_DUAL(vsplth, PPC_ALTIVEC, PPC_NONE,
|
||||
vextractuh, PPC_NONE, PPC2_ISA300);
|
||||
GEN_VXFORM_DUAL(vspltw, PPC_ALTIVEC, PPC_NONE,
|
||||
vextractuw, PPC_NONE, PPC2_ISA300);
|
||||
GEN_VXFORM_DUAL(vspltisb, PPC_ALTIVEC, PPC_NONE,
|
||||
vinsertb, PPC_NONE, PPC2_ISA300);
|
||||
GEN_VXFORM_DUAL(vspltish, PPC_ALTIVEC, PPC_NONE,
|
||||
vinserth, PPC_NONE, PPC2_ISA300);
|
||||
GEN_VXFORM_DUAL(vspltisw, PPC_ALTIVEC, PPC_NONE,
|
||||
vinsertw, PPC_NONE, PPC2_ISA300);
|
||||
|
||||
static void gen_vsldoi(DisasContext *ctx)
|
||||
{
|
||||
@ -798,6 +819,8 @@ GEN_VXFORM_NOA_2(vctzb, 1, 24, 28)
|
||||
GEN_VXFORM_NOA_2(vctzh, 1, 24, 29)
|
||||
GEN_VXFORM_NOA_2(vctzw, 1, 24, 30)
|
||||
GEN_VXFORM_NOA_2(vctzd, 1, 24, 31)
|
||||
GEN_VXFORM_NOA_3(vclzlsbb, 1, 24, 0)
|
||||
GEN_VXFORM_NOA_3(vctzlsbb, 1, 24, 1)
|
||||
GEN_VXFORM_NOA(vpopcntb, 1, 28)
|
||||
GEN_VXFORM_NOA(vpopcnth, 1, 29)
|
||||
GEN_VXFORM_NOA(vpopcntw, 1, 30)
|
||||
|
@ -181,9 +181,6 @@ GEN_HANDLER2_E(name, str, 0x4, opc2, opc3, 0x00000000, PPC_NONE, PPC2_ISA300),
|
||||
GEN_VXRFORM1_300(name, name, #name, opc2, opc3) \
|
||||
GEN_VXRFORM1_300(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
|
||||
|
||||
GEN_VXRFORM(vcmpequb, 3, 0)
|
||||
GEN_VXRFORM(vcmpequh, 3, 1)
|
||||
GEN_VXRFORM(vcmpequw, 3, 2)
|
||||
GEN_VXRFORM_300(vcmpnezb, 3, 4)
|
||||
GEN_VXRFORM_300(vcmpnezh, 3, 5)
|
||||
GEN_VXRFORM_300(vcmpnezw, 3, 6)
|
||||
@ -197,28 +194,33 @@ GEN_VXRFORM_DUAL(vcmpeqfp, vcmpequd, 3, 3, PPC_ALTIVEC, PPC_NONE)
|
||||
GEN_VXRFORM(vcmpgefp, 3, 7)
|
||||
GEN_VXRFORM_DUAL(vcmpgtfp, vcmpgtud, 3, 11, PPC_ALTIVEC, PPC_NONE)
|
||||
GEN_VXRFORM_DUAL(vcmpbfp, vcmpgtsd, 3, 15, PPC_ALTIVEC, PPC_NONE)
|
||||
GEN_VXRFORM_DUAL(vcmpequb, vcmpneb, 3, 0, PPC_ALTIVEC, PPC_NONE)
|
||||
GEN_VXRFORM_DUAL(vcmpequh, vcmpneh, 3, 1, PPC_ALTIVEC, PPC_NONE)
|
||||
GEN_VXRFORM_DUAL(vcmpequw, vcmpnew, 3, 2, PPC_ALTIVEC, PPC_NONE)
|
||||
|
||||
#define GEN_VXFORM_DUAL_INV(name0, name1, opc2, opc3, inval0, inval1, type) \
|
||||
GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, \
|
||||
PPC_NONE)
|
||||
GEN_VXFORM_DUAL_INV(vspltb, vextractub, 6, 8, 0x00000000, 0x100000,
|
||||
PPC2_ALTIVEC_207),
|
||||
PPC_ALTIVEC),
|
||||
GEN_VXFORM_DUAL_INV(vsplth, vextractuh, 6, 9, 0x00000000, 0x100000,
|
||||
PPC2_ALTIVEC_207),
|
||||
PPC_ALTIVEC),
|
||||
GEN_VXFORM_DUAL_INV(vspltw, vextractuw, 6, 10, 0x00000000, 0x100000,
|
||||
PPC2_ALTIVEC_207),
|
||||
PPC_ALTIVEC),
|
||||
GEN_VXFORM_300_EXT(vextractd, 6, 11, 0x100000),
|
||||
GEN_VXFORM_DUAL_INV(vspltisb, vinsertb, 6, 12, 0x00000000, 0x100000,
|
||||
PPC2_ALTIVEC_207),
|
||||
PPC_ALTIVEC),
|
||||
GEN_VXFORM_DUAL_INV(vspltish, vinserth, 6, 13, 0x00000000, 0x100000,
|
||||
PPC2_ALTIVEC_207),
|
||||
PPC_ALTIVEC),
|
||||
GEN_VXFORM_DUAL_INV(vspltisw, vinsertw, 6, 14, 0x00000000, 0x100000,
|
||||
PPC2_ALTIVEC_207),
|
||||
PPC_ALTIVEC),
|
||||
GEN_VXFORM_300_EXT(vinsertd, 6, 15, 0x100000),
|
||||
GEN_VXFORM_300_EO(vctzb, 0x01, 0x18, 0x1C),
|
||||
GEN_VXFORM_300_EO(vctzh, 0x01, 0x18, 0x1D),
|
||||
GEN_VXFORM_300_EO(vctzw, 0x01, 0x18, 0x1E),
|
||||
GEN_VXFORM_300_EO(vctzd, 0x01, 0x18, 0x1F),
|
||||
GEN_VXFORM_300_EO(vclzlsbb, 0x01, 0x18, 0x0),
|
||||
GEN_VXFORM_300_EO(vctzlsbb, 0x01, 0x18, 0x1),
|
||||
GEN_VXFORM_300(vpermr, 0x1D, 0xFF),
|
||||
|
||||
#define GEN_VXFORM_NOA(name, opc2, opc3) \
|
||||
|
@ -75,7 +75,6 @@ static void gen_lxvdsx(DisasContext *ctx)
|
||||
static void gen_lxvw4x(DisasContext *ctx)
|
||||
{
|
||||
TCGv EA;
|
||||
TCGv_i64 tmp;
|
||||
TCGv_i64 xth = cpu_vsrh(xT(ctx->opcode));
|
||||
TCGv_i64 xtl = cpu_vsrl(xT(ctx->opcode));
|
||||
if (unlikely(!ctx->vsx_enabled)) {
|
||||
@ -84,22 +83,95 @@ static void gen_lxvw4x(DisasContext *ctx)
|
||||
}
|
||||
gen_set_access_type(ctx, ACCESS_INT);
|
||||
EA = tcg_temp_new();
|
||||
tmp = tcg_temp_new_i64();
|
||||
|
||||
gen_addr_reg_index(ctx, EA);
|
||||
gen_qemu_ld32u_i64(ctx, tmp, EA);
|
||||
tcg_gen_addi_tl(EA, EA, 4);
|
||||
gen_qemu_ld32u_i64(ctx, xth, EA);
|
||||
tcg_gen_deposit_i64(xth, xth, tmp, 32, 32);
|
||||
|
||||
tcg_gen_addi_tl(EA, EA, 4);
|
||||
gen_qemu_ld32u_i64(ctx, tmp, EA);
|
||||
tcg_gen_addi_tl(EA, EA, 4);
|
||||
gen_qemu_ld32u_i64(ctx, xtl, EA);
|
||||
tcg_gen_deposit_i64(xtl, xtl, tmp, 32, 32);
|
||||
if (ctx->le_mode) {
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEQ);
|
||||
tcg_gen_shri_i64(t1, t0, 32);
|
||||
tcg_gen_deposit_i64(xth, t1, t0, 32, 32);
|
||||
tcg_gen_addi_tl(EA, EA, 8);
|
||||
tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEQ);
|
||||
tcg_gen_shri_i64(t1, t0, 32);
|
||||
tcg_gen_deposit_i64(xtl, t1, t0, 32, 32);
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
} else {
|
||||
tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
|
||||
tcg_gen_addi_tl(EA, EA, 8);
|
||||
tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
|
||||
}
|
||||
tcg_temp_free(EA);
|
||||
}
|
||||
|
||||
static void gen_bswap16x8(TCGv_i64 outh, TCGv_i64 outl,
|
||||
TCGv_i64 inh, TCGv_i64 inl)
|
||||
{
|
||||
TCGv_i64 mask = tcg_const_i64(0x00FF00FF00FF00FF);
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
|
||||
/* outh = ((inh & mask) << 8) | ((inh >> 8) & mask) */
|
||||
tcg_gen_and_i64(t0, inh, mask);
|
||||
tcg_gen_shli_i64(t0, t0, 8);
|
||||
tcg_gen_shri_i64(t1, inh, 8);
|
||||
tcg_gen_and_i64(t1, t1, mask);
|
||||
tcg_gen_or_i64(outh, t0, t1);
|
||||
|
||||
/* outl = ((inl & mask) << 8) | ((inl >> 8) & mask) */
|
||||
tcg_gen_and_i64(t0, inl, mask);
|
||||
tcg_gen_shli_i64(t0, t0, 8);
|
||||
tcg_gen_shri_i64(t1, inl, 8);
|
||||
tcg_gen_and_i64(t1, t1, mask);
|
||||
tcg_gen_or_i64(outl, t0, t1);
|
||||
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(mask);
|
||||
}
|
||||
|
||||
static void gen_lxvh8x(DisasContext *ctx)
|
||||
{
|
||||
TCGv EA;
|
||||
TCGv_i64 xth = cpu_vsrh(xT(ctx->opcode));
|
||||
TCGv_i64 xtl = cpu_vsrl(xT(ctx->opcode));
|
||||
|
||||
if (unlikely(!ctx->vsx_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VSXU);
|
||||
return;
|
||||
}
|
||||
gen_set_access_type(ctx, ACCESS_INT);
|
||||
|
||||
EA = tcg_temp_new();
|
||||
gen_addr_reg_index(ctx, EA);
|
||||
tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
|
||||
tcg_gen_addi_tl(EA, EA, 8);
|
||||
tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
|
||||
if (ctx->le_mode) {
|
||||
gen_bswap16x8(xth, xtl, xth, xtl);
|
||||
}
|
||||
tcg_temp_free(EA);
|
||||
}
|
||||
|
||||
static void gen_lxvb16x(DisasContext *ctx)
|
||||
{
|
||||
TCGv EA;
|
||||
TCGv_i64 xth = cpu_vsrh(xT(ctx->opcode));
|
||||
TCGv_i64 xtl = cpu_vsrl(xT(ctx->opcode));
|
||||
|
||||
if (unlikely(!ctx->vsx_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VSXU);
|
||||
return;
|
||||
}
|
||||
gen_set_access_type(ctx, ACCESS_INT);
|
||||
EA = tcg_temp_new();
|
||||
gen_addr_reg_index(ctx, EA);
|
||||
tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
|
||||
tcg_gen_addi_tl(EA, EA, 8);
|
||||
tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
|
||||
tcg_temp_free(EA);
|
||||
tcg_temp_free_i64(tmp);
|
||||
}
|
||||
|
||||
#define VSX_STORE_SCALAR(name, operation) \
|
||||
@ -142,7 +214,8 @@ static void gen_stxvd2x(DisasContext *ctx)
|
||||
|
||||
static void gen_stxvw4x(DisasContext *ctx)
|
||||
{
|
||||
TCGv_i64 tmp;
|
||||
TCGv_i64 xsh = cpu_vsrh(xS(ctx->opcode));
|
||||
TCGv_i64 xsl = cpu_vsrl(xS(ctx->opcode));
|
||||
TCGv EA;
|
||||
if (unlikely(!ctx->vsx_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VSXU);
|
||||
@ -151,21 +224,75 @@ static void gen_stxvw4x(DisasContext *ctx)
|
||||
gen_set_access_type(ctx, ACCESS_INT);
|
||||
EA = tcg_temp_new();
|
||||
gen_addr_reg_index(ctx, EA);
|
||||
tmp = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_shri_i64(tmp, cpu_vsrh(xS(ctx->opcode)), 32);
|
||||
gen_qemu_st32_i64(ctx, tmp, EA);
|
||||
tcg_gen_addi_tl(EA, EA, 4);
|
||||
gen_qemu_st32_i64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
|
||||
|
||||
tcg_gen_shri_i64(tmp, cpu_vsrl(xS(ctx->opcode)), 32);
|
||||
tcg_gen_addi_tl(EA, EA, 4);
|
||||
gen_qemu_st32_i64(ctx, tmp, EA);
|
||||
tcg_gen_addi_tl(EA, EA, 4);
|
||||
gen_qemu_st32_i64(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
|
||||
if (ctx->le_mode) {
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_shri_i64(t0, xsh, 32);
|
||||
tcg_gen_deposit_i64(t1, t0, xsh, 32, 32);
|
||||
tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEQ);
|
||||
tcg_gen_addi_tl(EA, EA, 8);
|
||||
tcg_gen_shri_i64(t0, xsl, 32);
|
||||
tcg_gen_deposit_i64(t1, t0, xsl, 32, 32);
|
||||
tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEQ);
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
} else {
|
||||
tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
|
||||
tcg_gen_addi_tl(EA, EA, 8);
|
||||
tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
|
||||
}
|
||||
tcg_temp_free(EA);
|
||||
}
|
||||
|
||||
static void gen_stxvh8x(DisasContext *ctx)
|
||||
{
|
||||
TCGv_i64 xsh = cpu_vsrh(xS(ctx->opcode));
|
||||
TCGv_i64 xsl = cpu_vsrl(xS(ctx->opcode));
|
||||
TCGv EA;
|
||||
|
||||
if (unlikely(!ctx->vsx_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VSXU);
|
||||
return;
|
||||
}
|
||||
gen_set_access_type(ctx, ACCESS_INT);
|
||||
EA = tcg_temp_new();
|
||||
gen_addr_reg_index(ctx, EA);
|
||||
if (ctx->le_mode) {
|
||||
TCGv_i64 outh = tcg_temp_new_i64();
|
||||
TCGv_i64 outl = tcg_temp_new_i64();
|
||||
|
||||
gen_bswap16x8(outh, outl, xsh, xsl);
|
||||
tcg_gen_qemu_st_i64(outh, EA, ctx->mem_idx, MO_BEQ);
|
||||
tcg_gen_addi_tl(EA, EA, 8);
|
||||
tcg_gen_qemu_st_i64(outl, EA, ctx->mem_idx, MO_BEQ);
|
||||
tcg_temp_free_i64(outh);
|
||||
tcg_temp_free_i64(outl);
|
||||
} else {
|
||||
tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
|
||||
tcg_gen_addi_tl(EA, EA, 8);
|
||||
tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
|
||||
}
|
||||
tcg_temp_free(EA);
|
||||
}
|
||||
|
||||
static void gen_stxvb16x(DisasContext *ctx)
|
||||
{
|
||||
TCGv_i64 xsh = cpu_vsrh(xS(ctx->opcode));
|
||||
TCGv_i64 xsl = cpu_vsrl(xS(ctx->opcode));
|
||||
TCGv EA;
|
||||
|
||||
if (unlikely(!ctx->vsx_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VSXU);
|
||||
return;
|
||||
}
|
||||
gen_set_access_type(ctx, ACCESS_INT);
|
||||
EA = tcg_temp_new();
|
||||
gen_addr_reg_index(ctx, EA);
|
||||
tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
|
||||
tcg_gen_addi_tl(EA, EA, 8);
|
||||
tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
|
||||
tcg_temp_free(EA);
|
||||
tcg_temp_free_i64(tmp);
|
||||
}
|
||||
|
||||
#define MV_VSRW(name, tcgop1, tcgop2, target, source) \
|
||||
@ -217,6 +344,65 @@ static void gen_##name(DisasContext *ctx) \
|
||||
MV_VSRD(mfvsrd, cpu_gpr[rA(ctx->opcode)], cpu_vsrh(xS(ctx->opcode)))
|
||||
MV_VSRD(mtvsrd, cpu_vsrh(xT(ctx->opcode)), cpu_gpr[rA(ctx->opcode)])
|
||||
|
||||
static void gen_mfvsrld(DisasContext *ctx)
|
||||
{
|
||||
if (xS(ctx->opcode) < 32) {
|
||||
if (unlikely(!ctx->vsx_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VSXU);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (unlikely(!ctx->altivec_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VPU);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
tcg_gen_mov_i64(cpu_gpr[rA(ctx->opcode)], cpu_vsrl(xS(ctx->opcode)));
|
||||
}
|
||||
|
||||
static void gen_mtvsrdd(DisasContext *ctx)
|
||||
{
|
||||
if (xT(ctx->opcode) < 32) {
|
||||
if (unlikely(!ctx->vsx_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VSXU);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (unlikely(!ctx->altivec_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VPU);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rA(ctx->opcode)) {
|
||||
tcg_gen_movi_i64(cpu_vsrh(xT(ctx->opcode)), 0);
|
||||
} else {
|
||||
tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
|
||||
tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_gpr[rB(ctx->opcode)]);
|
||||
}
|
||||
|
||||
static void gen_mtvsrws(DisasContext *ctx)
|
||||
{
|
||||
if (xT(ctx->opcode) < 32) {
|
||||
if (unlikely(!ctx->vsx_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VSXU);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (unlikely(!ctx->altivec_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_VPU);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
tcg_gen_deposit_i64(cpu_vsrl(xT(ctx->opcode)), cpu_gpr[rA(ctx->opcode)],
|
||||
cpu_gpr[rA(ctx->opcode)], 32, 32);
|
||||
tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrl(xT(ctx->opcode)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void gen_xxpermdi(DisasContext *ctx)
|
||||
|
@ -7,6 +7,8 @@ GEN_HANDLER_E(lxsspx, 0x1F, 0x0C, 0x10, 0, PPC_NONE, PPC2_VSX207),
|
||||
GEN_HANDLER_E(lxvd2x, 0x1F, 0x0C, 0x1A, 0, PPC_NONE, PPC2_VSX),
|
||||
GEN_HANDLER_E(lxvdsx, 0x1F, 0x0C, 0x0A, 0, PPC_NONE, PPC2_VSX),
|
||||
GEN_HANDLER_E(lxvw4x, 0x1F, 0x0C, 0x18, 0, PPC_NONE, PPC2_VSX),
|
||||
GEN_HANDLER_E(lxvh8x, 0x1F, 0x0C, 0x19, 0, PPC_NONE, PPC2_ISA300),
|
||||
GEN_HANDLER_E(lxvb16x, 0x1F, 0x0C, 0x1B, 0, PPC_NONE, PPC2_ISA300),
|
||||
|
||||
GEN_HANDLER_E(stxsdx, 0x1F, 0xC, 0x16, 0, PPC_NONE, PPC2_VSX),
|
||||
GEN_HANDLER_E(stxsibx, 0x1F, 0xD, 0x1C, 0, PPC_NONE, PPC2_ISA300),
|
||||
@ -15,6 +17,8 @@ GEN_HANDLER_E(stxsiwx, 0x1F, 0xC, 0x04, 0, PPC_NONE, PPC2_VSX207),
|
||||
GEN_HANDLER_E(stxsspx, 0x1F, 0xC, 0x14, 0, PPC_NONE, PPC2_VSX207),
|
||||
GEN_HANDLER_E(stxvd2x, 0x1F, 0xC, 0x1E, 0, PPC_NONE, PPC2_VSX),
|
||||
GEN_HANDLER_E(stxvw4x, 0x1F, 0xC, 0x1C, 0, PPC_NONE, PPC2_VSX),
|
||||
GEN_HANDLER_E(stxvh8x, 0x1F, 0x0C, 0x1D, 0, PPC_NONE, PPC2_ISA300),
|
||||
GEN_HANDLER_E(stxvb16x, 0x1F, 0x0C, 0x1F, 0, PPC_NONE, PPC2_ISA300),
|
||||
|
||||
GEN_HANDLER_E(mfvsrwz, 0x1F, 0x13, 0x03, 0x0000F800, PPC_NONE, PPC2_VSX207),
|
||||
GEN_HANDLER_E(mtvsrwa, 0x1F, 0x13, 0x06, 0x0000F800, PPC_NONE, PPC2_VSX207),
|
||||
@ -22,6 +26,9 @@ GEN_HANDLER_E(mtvsrwz, 0x1F, 0x13, 0x07, 0x0000F800, PPC_NONE, PPC2_VSX207),
|
||||
#if defined(TARGET_PPC64)
|
||||
GEN_HANDLER_E(mfvsrd, 0x1F, 0x13, 0x01, 0x0000F800, PPC_NONE, PPC2_VSX207),
|
||||
GEN_HANDLER_E(mtvsrd, 0x1F, 0x13, 0x05, 0x0000F800, PPC_NONE, PPC2_VSX207),
|
||||
GEN_HANDLER_E(mfvsrld, 0X1F, 0x13, 0x09, 0x0000F800, PPC_NONE, PPC2_ISA300),
|
||||
GEN_HANDLER_E(mtvsrdd, 0X1F, 0x13, 0x0D, 0x0, PPC_NONE, PPC2_ISA300),
|
||||
GEN_HANDLER_E(mtvsrws, 0x1F, 0x13, 0x0C, 0x0000F800, PPC_NONE, PPC2_ISA300),
|
||||
#endif
|
||||
|
||||
#define GEN_XX1FORM(name, opc2, opc3, fl2) \
|
||||
|
@ -271,6 +271,13 @@ check-qtest-ppc64-y += tests/drive_del-test$(EXESUF)
|
||||
check-qtest-ppc64-y += tests/postcopy-test$(EXESUF)
|
||||
check-qtest-ppc64-y += tests/boot-serial-test$(EXESUF)
|
||||
check-qtest-ppc64-y += tests/rtas-test$(EXESUF)
|
||||
check-qtest-ppc64-y += tests/pxe-test$(EXESUF)
|
||||
check-qtest-ppc64-y += tests/usb-hcd-ohci-test$(EXESUF)
|
||||
gcov-files-ppc64-y += hw/usb/hcd-ohci.c
|
||||
check-qtest-ppc64-y += tests/usb-hcd-uhci-test$(EXESUF)
|
||||
gcov-files-ppc64-y += hw/usb/hcd-uhci.c
|
||||
check-qtest-ppc64-y += tests/usb-hcd-xhci-test$(EXESUF)
|
||||
gcov-files-ppc64-y += hw/usb/hcd-xhci.c
|
||||
|
||||
check-qtest-sh4-y = tests/endianness-test$(EXESUF)
|
||||
|
||||
@ -590,12 +597,13 @@ libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o
|
||||
libqos-spapr-obj-y = $(libqos-obj-y) tests/libqos/malloc-spapr.o
|
||||
libqos-spapr-obj-y += tests/libqos/libqos-spapr.o
|
||||
libqos-spapr-obj-y += tests/libqos/rtas.o
|
||||
libqos-spapr-obj-y += tests/libqos/pci-spapr.o
|
||||
libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
|
||||
libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o
|
||||
libqos-pc-obj-y += tests/libqos/ahci.o
|
||||
libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o
|
||||
libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o
|
||||
libqos-usb-obj-y = $(libqos-pc-obj-y) tests/libqos/usb.o
|
||||
libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/usb.o
|
||||
libqos-virtio-obj-y = $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o tests/libqos/malloc-generic.o
|
||||
|
||||
tests/device-introspect-test$(EXESUF): tests/device-introspect-test.o
|
||||
|
@ -77,6 +77,15 @@ int boot_sector_init(const char *fname)
|
||||
fprintf(stderr, "Couldn't open \"%s\": %s", fname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* For Open Firmware based system, we can use a Forth script instead */
|
||||
if (strcmp(qtest_get_arch(), "ppc64") == 0) {
|
||||
memset(boot_sector, ' ', sizeof boot_sector);
|
||||
sprintf((char *)boot_sector, "\\ Bootscript\n%x %x c! %x %x c!\n",
|
||||
LOW(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET,
|
||||
HIGH(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
|
||||
}
|
||||
|
||||
fwrite(boot_sector, 1, sizeof boot_sector, f);
|
||||
fclose(f);
|
||||
return 0;
|
||||
|
@ -390,7 +390,7 @@ static void data_test_init(e1000e_device *d)
|
||||
qtest_start(cmdline);
|
||||
g_free(cmdline);
|
||||
|
||||
test_bus = qpci_init_pc();
|
||||
test_bus = qpci_init_pc(NULL);
|
||||
g_assert_nonnull(test_bus);
|
||||
|
||||
test_alloc = pc_alloc_init();
|
||||
|
@ -38,7 +38,7 @@ static QPCIBus *test_start_get_bus(const TestData *s)
|
||||
cmdline = g_strdup_printf("-smp %d", s->num_cpus);
|
||||
qtest_start(cmdline);
|
||||
g_free(cmdline);
|
||||
return qpci_init_pc();
|
||||
return qpci_init_pc(NULL);
|
||||
}
|
||||
|
||||
static void test_i440fx_defaults(gconstpointer opaque)
|
||||
|
@ -143,7 +143,7 @@ static QPCIDevice *get_pci_device(uint16_t *bmdma_base)
|
||||
uint16_t vendor_id, device_id;
|
||||
|
||||
if (!pcibus) {
|
||||
pcibus = qpci_init_pc();
|
||||
pcibus = qpci_init_pc(NULL);
|
||||
}
|
||||
|
||||
/* Find PCI device and verify it's the right one */
|
||||
|
@ -105,7 +105,7 @@ static void setup_vm_cmd(IVState *s, const char *cmd, bool msix)
|
||||
uint64_t barsize;
|
||||
|
||||
s->qtest = qtest_start(cmd);
|
||||
s->pcibus = qpci_init_pc();
|
||||
s->pcibus = qpci_init_pc(NULL);
|
||||
s->dev = get_device(s->pcibus);
|
||||
|
||||
s->reg_base = qpci_iomap(s->dev, 0, &barsize);
|
||||
|
@ -128,7 +128,7 @@ QPCIDevice *get_ahci_device(uint32_t *fingerprint)
|
||||
uint32_t ahci_fingerprint;
|
||||
QPCIBus *pcibus;
|
||||
|
||||
pcibus = qpci_init_pc();
|
||||
pcibus = qpci_init_pc(NULL);
|
||||
|
||||
/* Find the AHCI PCI device and verify it's the right one. */
|
||||
ahci = qpci_device_find(pcibus, QPCI_DEVFN(0x1F, 0x02));
|
||||
|
@ -1,10 +1,14 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "libqos/libqos-pc.h"
|
||||
#include "libqos/malloc-pc.h"
|
||||
#include "libqos/pci-pc.h"
|
||||
|
||||
static QOSOps qos_ops = {
|
||||
.init_allocator = pc_alloc_init_flags,
|
||||
.uninit_allocator = pc_alloc_uninit
|
||||
.uninit_allocator = pc_alloc_uninit,
|
||||
.qpci_init = qpci_init_pc,
|
||||
.qpci_free = qpci_free_pc,
|
||||
.shutdown = qtest_pc_shutdown,
|
||||
};
|
||||
|
||||
QOSState *qtest_pc_vboot(const char *cmdline_fmt, va_list ap)
|
||||
@ -28,5 +32,5 @@ QOSState *qtest_pc_boot(const char *cmdline_fmt, ...)
|
||||
|
||||
void qtest_pc_shutdown(QOSState *qs)
|
||||
{
|
||||
return qtest_shutdown(qs);
|
||||
return qtest_common_shutdown(qs);
|
||||
}
|
||||
|
@ -1,10 +1,14 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "libqos/libqos-spapr.h"
|
||||
#include "libqos/malloc-spapr.h"
|
||||
#include "libqos/pci-spapr.h"
|
||||
|
||||
static QOSOps qos_ops = {
|
||||
.init_allocator = spapr_alloc_init_flags,
|
||||
.uninit_allocator = spapr_alloc_uninit
|
||||
.uninit_allocator = spapr_alloc_uninit,
|
||||
.qpci_init = qpci_init_spapr,
|
||||
.qpci_free = qpci_free_spapr,
|
||||
.shutdown = qtest_spapr_shutdown,
|
||||
};
|
||||
|
||||
QOSState *qtest_spapr_vboot(const char *cmdline_fmt, va_list ap)
|
||||
@ -26,5 +30,5 @@ QOSState *qtest_spapr_boot(const char *cmdline_fmt, ...)
|
||||
|
||||
void qtest_spapr_shutdown(QOSState *qs)
|
||||
{
|
||||
return qtest_shutdown(qs);
|
||||
return qtest_common_shutdown(qs);
|
||||
}
|
||||
|
@ -20,8 +20,13 @@ QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap)
|
||||
cmdline = g_strdup_vprintf(cmdline_fmt, ap);
|
||||
qs->qts = qtest_start(cmdline);
|
||||
qs->ops = ops;
|
||||
if (ops && ops->init_allocator) {
|
||||
qs->alloc = ops->init_allocator(ALLOC_NO_FLAGS);
|
||||
if (ops) {
|
||||
if (ops->init_allocator) {
|
||||
qs->alloc = ops->init_allocator(ALLOC_NO_FLAGS);
|
||||
}
|
||||
if (ops->qpci_init && qs->alloc) {
|
||||
qs->pcibus = ops->qpci_init(qs->alloc);
|
||||
}
|
||||
}
|
||||
|
||||
g_free(cmdline);
|
||||
@ -47,16 +52,31 @@ QOSState *qtest_boot(QOSOps *ops, const char *cmdline_fmt, ...)
|
||||
/**
|
||||
* Tear down the QEMU instance.
|
||||
*/
|
||||
void qtest_shutdown(QOSState *qs)
|
||||
void qtest_common_shutdown(QOSState *qs)
|
||||
{
|
||||
if (qs->alloc && qs->ops && qs->ops->uninit_allocator) {
|
||||
qs->ops->uninit_allocator(qs->alloc);
|
||||
qs->alloc = NULL;
|
||||
if (qs->ops) {
|
||||
if (qs->pcibus && qs->ops->qpci_free) {
|
||||
qs->ops->qpci_free(qs->pcibus);
|
||||
qs->pcibus = NULL;
|
||||
}
|
||||
if (qs->alloc && qs->ops->uninit_allocator) {
|
||||
qs->ops->uninit_allocator(qs->alloc);
|
||||
qs->alloc = NULL;
|
||||
}
|
||||
}
|
||||
qtest_quit(qs->qts);
|
||||
g_free(qs);
|
||||
}
|
||||
|
||||
void qtest_shutdown(QOSState *qs)
|
||||
{
|
||||
if (qs->ops && qs->ops->shutdown) {
|
||||
qs->ops->shutdown(qs);
|
||||
} else {
|
||||
qtest_common_shutdown(qs);
|
||||
}
|
||||
}
|
||||
|
||||
void set_context(QOSState *s)
|
||||
{
|
||||
global_qtest = s->qts;
|
||||
|
@ -5,19 +5,26 @@
|
||||
#include "libqos/pci.h"
|
||||
#include "libqos/malloc-pc.h"
|
||||
|
||||
typedef struct QOSState QOSState;
|
||||
|
||||
typedef struct QOSOps {
|
||||
QGuestAllocator *(*init_allocator)(QAllocOpts);
|
||||
void (*uninit_allocator)(QGuestAllocator *);
|
||||
QPCIBus *(*qpci_init)(QGuestAllocator *alloc);
|
||||
void (*qpci_free)(QPCIBus *bus);
|
||||
void (*shutdown)(QOSState *);
|
||||
} QOSOps;
|
||||
|
||||
typedef struct QOSState {
|
||||
struct QOSState {
|
||||
QTestState *qts;
|
||||
QGuestAllocator *alloc;
|
||||
QPCIBus *pcibus;
|
||||
QOSOps *ops;
|
||||
} QOSState;
|
||||
};
|
||||
|
||||
QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap);
|
||||
QOSState *qtest_boot(QOSOps *ops, const char *cmdline_fmt, ...);
|
||||
void qtest_common_shutdown(QOSState *qs);
|
||||
void qtest_shutdown(QOSState *qs);
|
||||
bool have_qemu_img(void);
|
||||
void mkimg(const char *file, const char *fmt, unsigned size_mb);
|
||||
|
@ -212,7 +212,7 @@ static void qpci_pc_iounmap(QPCIBus *bus, void *data)
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
QPCIBus *qpci_init_pc(void)
|
||||
QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
|
||||
{
|
||||
QPCIBusPC *ret;
|
||||
|
||||
@ -255,28 +255,6 @@ void qpci_free_pc(QPCIBus *bus)
|
||||
g_free(s);
|
||||
}
|
||||
|
||||
void qpci_plug_device_test(const char *driver, const char *id,
|
||||
uint8_t slot, const char *opts)
|
||||
{
|
||||
QDict *response;
|
||||
char *cmd;
|
||||
|
||||
cmd = g_strdup_printf("{'execute': 'device_add',"
|
||||
" 'arguments': {"
|
||||
" 'driver': '%s',"
|
||||
" 'addr': '%d',"
|
||||
" %s%s"
|
||||
" 'id': '%s'"
|
||||
"}}", driver, slot,
|
||||
opts ? opts : "", opts ? "," : "",
|
||||
id);
|
||||
response = qmp(cmd);
|
||||
g_free(cmd);
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
QDECREF(response);
|
||||
}
|
||||
|
||||
void qpci_unplug_acpi_device_test(const char *id, uint8_t slot)
|
||||
{
|
||||
QDict *response;
|
||||
|
@ -14,8 +14,9 @@
|
||||
#define LIBQOS_PCI_PC_H
|
||||
|
||||
#include "libqos/pci.h"
|
||||
#include "libqos/malloc.h"
|
||||
|
||||
QPCIBus *qpci_init_pc(void);
|
||||
QPCIBus *qpci_init_pc(QGuestAllocator *alloc);
|
||||
void qpci_free_pc(QPCIBus *bus);
|
||||
|
||||
#endif
|
||||
|
288
tests/libqos/pci-spapr.c
Normal file
288
tests/libqos/pci-spapr.c
Normal file
@ -0,0 +1,288 @@
|
||||
/*
|
||||
* libqos PCI bindings for SPAPR
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "libqtest.h"
|
||||
#include "libqos/pci-spapr.h"
|
||||
#include "libqos/rtas.h"
|
||||
|
||||
#include "hw/pci/pci_regs.h"
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/host-utils.h"
|
||||
|
||||
|
||||
/* From include/hw/pci-host/spapr.h */
|
||||
|
||||
#define SPAPR_PCI_BASE_BUID 0x800000020000000ULL
|
||||
|
||||
#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
|
||||
|
||||
#define SPAPR_PCI_WINDOW_BASE 0x10000000000ULL
|
||||
#define SPAPR_PCI_WINDOW_SPACING 0x1000000000ULL
|
||||
#define SPAPR_PCI_MMIO_WIN_OFF 0xA0000000
|
||||
#define SPAPR_PCI_MMIO_WIN_SIZE (SPAPR_PCI_WINDOW_SPACING - \
|
||||
SPAPR_PCI_MEM_WIN_BUS_OFFSET)
|
||||
#define SPAPR_PCI_IO_WIN_OFF 0x80000000
|
||||
#define SPAPR_PCI_IO_WIN_SIZE 0x10000
|
||||
|
||||
/* index is the phb index */
|
||||
|
||||
#define BUIDBASE(index) (SPAPR_PCI_BASE_BUID + (index))
|
||||
#define PCIBASE(index) (SPAPR_PCI_WINDOW_BASE + \
|
||||
(index) * SPAPR_PCI_WINDOW_SPACING)
|
||||
#define IOBASE(index) (PCIBASE(index) + SPAPR_PCI_IO_WIN_OFF)
|
||||
#define MMIOBASE(index) (PCIBASE(index) + SPAPR_PCI_MMIO_WIN_OFF)
|
||||
|
||||
typedef struct QPCIBusSPAPR {
|
||||
QPCIBus bus;
|
||||
QGuestAllocator *alloc;
|
||||
|
||||
uint64_t pci_hole_start;
|
||||
uint64_t pci_hole_size;
|
||||
uint64_t pci_hole_alloc;
|
||||
|
||||
uint32_t pci_iohole_start;
|
||||
uint32_t pci_iohole_size;
|
||||
uint32_t pci_iohole_alloc;
|
||||
} QPCIBusSPAPR;
|
||||
|
||||
/*
|
||||
* PCI devices are always little-endian
|
||||
* SPAPR by default is big-endian
|
||||
* so PCI accessors need to swap data endianness
|
||||
*/
|
||||
|
||||
static uint8_t qpci_spapr_io_readb(QPCIBus *bus, void *addr)
|
||||
{
|
||||
uint64_t port = (uintptr_t)addr;
|
||||
uint8_t v;
|
||||
if (port < SPAPR_PCI_IO_WIN_SIZE) {
|
||||
v = readb(IOBASE(0) + port);
|
||||
} else {
|
||||
v = readb(MMIOBASE(0) + port);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static uint16_t qpci_spapr_io_readw(QPCIBus *bus, void *addr)
|
||||
{
|
||||
uint64_t port = (uintptr_t)addr;
|
||||
uint16_t v;
|
||||
if (port < SPAPR_PCI_IO_WIN_SIZE) {
|
||||
v = readw(IOBASE(0) + port);
|
||||
} else {
|
||||
v = readw(MMIOBASE(0) + port);
|
||||
}
|
||||
return bswap16(v);
|
||||
}
|
||||
|
||||
static uint32_t qpci_spapr_io_readl(QPCIBus *bus, void *addr)
|
||||
{
|
||||
uint64_t port = (uintptr_t)addr;
|
||||
uint32_t v;
|
||||
if (port < SPAPR_PCI_IO_WIN_SIZE) {
|
||||
v = readl(IOBASE(0) + port);
|
||||
} else {
|
||||
v = readl(MMIOBASE(0) + port);
|
||||
}
|
||||
return bswap32(v);
|
||||
}
|
||||
|
||||
static void qpci_spapr_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
|
||||
{
|
||||
uint64_t port = (uintptr_t)addr;
|
||||
if (port < SPAPR_PCI_IO_WIN_SIZE) {
|
||||
writeb(IOBASE(0) + port, value);
|
||||
} else {
|
||||
writeb(MMIOBASE(0) + port, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void qpci_spapr_io_writew(QPCIBus *bus, void *addr, uint16_t value)
|
||||
{
|
||||
uint64_t port = (uintptr_t)addr;
|
||||
value = bswap16(value);
|
||||
if (port < SPAPR_PCI_IO_WIN_SIZE) {
|
||||
writew(IOBASE(0) + port, value);
|
||||
} else {
|
||||
writew(MMIOBASE(0) + port, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void qpci_spapr_io_writel(QPCIBus *bus, void *addr, uint32_t value)
|
||||
{
|
||||
uint64_t port = (uintptr_t)addr;
|
||||
value = bswap32(value);
|
||||
if (port < SPAPR_PCI_IO_WIN_SIZE) {
|
||||
writel(IOBASE(0) + port, value);
|
||||
} else {
|
||||
writel(MMIOBASE(0) + port, value);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t qpci_spapr_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
|
||||
{
|
||||
QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
|
||||
uint32_t config_addr = (devfn << 8) | offset;
|
||||
return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0),
|
||||
config_addr, 1);
|
||||
}
|
||||
|
||||
static uint16_t qpci_spapr_config_readw(QPCIBus *bus, int devfn, uint8_t offset)
|
||||
{
|
||||
QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
|
||||
uint32_t config_addr = (devfn << 8) | offset;
|
||||
return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0),
|
||||
config_addr, 2);
|
||||
}
|
||||
|
||||
static uint32_t qpci_spapr_config_readl(QPCIBus *bus, int devfn, uint8_t offset)
|
||||
{
|
||||
QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
|
||||
uint32_t config_addr = (devfn << 8) | offset;
|
||||
return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0),
|
||||
config_addr, 4);
|
||||
}
|
||||
|
||||
static void qpci_spapr_config_writeb(QPCIBus *bus, int devfn, uint8_t offset,
|
||||
uint8_t value)
|
||||
{
|
||||
QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
|
||||
uint32_t config_addr = (devfn << 8) | offset;
|
||||
qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0),
|
||||
config_addr, 1, value);
|
||||
}
|
||||
|
||||
static void qpci_spapr_config_writew(QPCIBus *bus, int devfn, uint8_t offset,
|
||||
uint16_t value)
|
||||
{
|
||||
QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
|
||||
uint32_t config_addr = (devfn << 8) | offset;
|
||||
qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0),
|
||||
config_addr, 2, value);
|
||||
}
|
||||
|
||||
static void qpci_spapr_config_writel(QPCIBus *bus, int devfn, uint8_t offset,
|
||||
uint32_t value)
|
||||
{
|
||||
QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
|
||||
uint32_t config_addr = (devfn << 8) | offset;
|
||||
qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0),
|
||||
config_addr, 4, value);
|
||||
}
|
||||
|
||||
static void *qpci_spapr_iomap(QPCIBus *bus, QPCIDevice *dev, int barno,
|
||||
uint64_t *sizeptr)
|
||||
{
|
||||
QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
|
||||
static const int bar_reg_map[] = {
|
||||
PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
|
||||
PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
|
||||
};
|
||||
int bar_reg;
|
||||
uint32_t addr;
|
||||
uint64_t size;
|
||||
uint32_t io_type;
|
||||
|
||||
g_assert(barno >= 0 && barno <= 5);
|
||||
bar_reg = bar_reg_map[barno];
|
||||
|
||||
qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
|
||||
addr = qpci_config_readl(dev, bar_reg);
|
||||
|
||||
io_type = addr & PCI_BASE_ADDRESS_SPACE;
|
||||
if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
|
||||
addr &= PCI_BASE_ADDRESS_IO_MASK;
|
||||
} else {
|
||||
addr &= PCI_BASE_ADDRESS_MEM_MASK;
|
||||
}
|
||||
|
||||
size = (1ULL << ctzl(addr));
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (sizeptr) {
|
||||
*sizeptr = size;
|
||||
}
|
||||
|
||||
if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
|
||||
uint16_t loc;
|
||||
|
||||
g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
|
||||
<= s->pci_iohole_size);
|
||||
s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
|
||||
loc = s->pci_iohole_start + s->pci_iohole_alloc;
|
||||
s->pci_iohole_alloc += size;
|
||||
|
||||
qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
|
||||
|
||||
return (void *)(unsigned long)loc;
|
||||
} else {
|
||||
uint64_t loc;
|
||||
|
||||
g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
|
||||
<= s->pci_hole_size);
|
||||
s->pci_hole_alloc = QEMU_ALIGN_UP(s->pci_hole_alloc, size);
|
||||
loc = s->pci_hole_start + s->pci_hole_alloc;
|
||||
s->pci_hole_alloc += size;
|
||||
|
||||
qpci_config_writel(dev, bar_reg, loc);
|
||||
|
||||
return (void *)(unsigned long)loc;
|
||||
}
|
||||
}
|
||||
|
||||
static void qpci_spapr_iounmap(QPCIBus *bus, void *data)
|
||||
{
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
|
||||
{
|
||||
QPCIBusSPAPR *ret;
|
||||
|
||||
ret = g_malloc(sizeof(*ret));
|
||||
|
||||
ret->alloc = alloc;
|
||||
|
||||
ret->bus.io_readb = qpci_spapr_io_readb;
|
||||
ret->bus.io_readw = qpci_spapr_io_readw;
|
||||
ret->bus.io_readl = qpci_spapr_io_readl;
|
||||
|
||||
ret->bus.io_writeb = qpci_spapr_io_writeb;
|
||||
ret->bus.io_writew = qpci_spapr_io_writew;
|
||||
ret->bus.io_writel = qpci_spapr_io_writel;
|
||||
|
||||
ret->bus.config_readb = qpci_spapr_config_readb;
|
||||
ret->bus.config_readw = qpci_spapr_config_readw;
|
||||
ret->bus.config_readl = qpci_spapr_config_readl;
|
||||
|
||||
ret->bus.config_writeb = qpci_spapr_config_writeb;
|
||||
ret->bus.config_writew = qpci_spapr_config_writew;
|
||||
ret->bus.config_writel = qpci_spapr_config_writel;
|
||||
|
||||
ret->bus.iomap = qpci_spapr_iomap;
|
||||
ret->bus.iounmap = qpci_spapr_iounmap;
|
||||
|
||||
ret->pci_hole_start = 0xC0000000;
|
||||
ret->pci_hole_size = SPAPR_PCI_MMIO_WIN_SIZE;
|
||||
ret->pci_hole_alloc = 0;
|
||||
|
||||
ret->pci_iohole_start = 0xc000;
|
||||
ret->pci_iohole_size = SPAPR_PCI_IO_WIN_SIZE;
|
||||
ret->pci_iohole_alloc = 0;
|
||||
|
||||
return &ret->bus;
|
||||
}
|
||||
|
||||
void qpci_free_spapr(QPCIBus *bus)
|
||||
{
|
||||
QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
|
||||
|
||||
g_free(s);
|
||||
}
|
17
tests/libqos/pci-spapr.h
Normal file
17
tests/libqos/pci-spapr.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* libqos PCI bindings for SPAPR
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef LIBQOS_PCI_SPAPR_H
|
||||
#define LIBQOS_PCI_SPAPR_H
|
||||
|
||||
#include "libqos/malloc.h"
|
||||
#include "libqos/pci.h"
|
||||
|
||||
QPCIBus *qpci_init_spapr(QGuestAllocator *alloc);
|
||||
void qpci_free_spapr(QPCIBus *bus);
|
||||
|
||||
#endif
|
@ -263,4 +263,24 @@ void qpci_iounmap(QPCIDevice *dev, void *data)
|
||||
dev->bus->iounmap(dev->bus, data);
|
||||
}
|
||||
|
||||
void qpci_plug_device_test(const char *driver, const char *id,
|
||||
uint8_t slot, const char *opts)
|
||||
{
|
||||
QDict *response;
|
||||
char *cmd;
|
||||
|
||||
cmd = g_strdup_printf("{'execute': 'device_add',"
|
||||
" 'arguments': {"
|
||||
" 'driver': '%s',"
|
||||
" 'addr': '%d',"
|
||||
" %s%s"
|
||||
" 'id': '%s'"
|
||||
"}}", driver, slot,
|
||||
opts ? opts : "", opts ? "," : "",
|
||||
id);
|
||||
response = qmp(cmd);
|
||||
g_free(cmd);
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
QDECREF(response);
|
||||
}
|
||||
|
@ -69,3 +69,48 @@ int qrtas_get_time_of_day(QGuestAllocator *alloc, struct tm *tm, uint32_t *ns)
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t qrtas_ibm_read_pci_config(QGuestAllocator *alloc, uint64_t buid,
|
||||
uint32_t addr, uint32_t size)
|
||||
{
|
||||
int res;
|
||||
uint32_t args[4], ret[2];
|
||||
|
||||
args[0] = addr;
|
||||
args[1] = buid >> 32;
|
||||
args[2] = buid & 0xffffffff;
|
||||
args[3] = size;
|
||||
res = qrtas_call(alloc, "ibm,read-pci-config", 4, args, 2, ret);
|
||||
if (res != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret[0] != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret[1];
|
||||
}
|
||||
|
||||
int qrtas_ibm_write_pci_config(QGuestAllocator *alloc, uint64_t buid,
|
||||
uint32_t addr, uint32_t size, uint32_t val)
|
||||
{
|
||||
int res;
|
||||
uint32_t args[5], ret[1];
|
||||
|
||||
args[0] = addr;
|
||||
args[1] = buid >> 32;
|
||||
args[2] = buid & 0xffffffff;
|
||||
args[3] = size;
|
||||
args[4] = val;
|
||||
res = qrtas_call(alloc, "ibm,write-pci-config", 5, args, 1, ret);
|
||||
if (res != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret[0] != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -8,4 +8,8 @@
|
||||
#include "libqos/malloc.h"
|
||||
|
||||
int qrtas_get_time_of_day(QGuestAllocator *alloc, struct tm *tm, uint32_t *ns);
|
||||
uint32_t qrtas_ibm_read_pci_config(QGuestAllocator *alloc, uint64_t buid,
|
||||
uint32_t addr, uint32_t size);
|
||||
int qrtas_ibm_write_pci_config(QGuestAllocator *alloc, uint64_t buid,
|
||||
uint32_t addr, uint32_t size, uint32_t val);
|
||||
#endif /* LIBQOS_RTAS_H */
|
||||
|
@ -21,14 +21,14 @@
|
||||
|
||||
static const char *disk = "tests/pxe-test-disk.raw";
|
||||
|
||||
static void test_pxe_one(const char *params)
|
||||
static void test_pxe_one(const char *params, bool ipv6)
|
||||
{
|
||||
char *args;
|
||||
|
||||
args = g_strdup_printf("-machine accel=tcg "
|
||||
"-netdev user,id=" NETNAME ",tftp=./,bootfile=%s "
|
||||
"%s ",
|
||||
disk, params);
|
||||
args = g_strdup_printf("-machine accel=tcg -nodefaults -boot order=n "
|
||||
"-netdev user,id=" NETNAME ",tftp=./,bootfile=%s,"
|
||||
"ipv4=%s,ipv6=%s %s", disk, ipv6 ? "off" : "on",
|
||||
ipv6 ? "on" : "off", params);
|
||||
|
||||
qtest_start(args);
|
||||
boot_sector_test();
|
||||
@ -38,12 +38,17 @@ static void test_pxe_one(const char *params)
|
||||
|
||||
static void test_pxe_e1000(void)
|
||||
{
|
||||
test_pxe_one("-device e1000,netdev=" NETNAME);
|
||||
test_pxe_one("-device e1000,netdev=" NETNAME, false);
|
||||
}
|
||||
|
||||
static void test_pxe_virtio_pci(void)
|
||||
{
|
||||
test_pxe_one("-device virtio-net-pci,netdev=" NETNAME);
|
||||
test_pxe_one("-device virtio-net-pci,netdev=" NETNAME, false);
|
||||
}
|
||||
|
||||
static void test_pxe_spapr_vlan(void)
|
||||
{
|
||||
test_pxe_one("-device spapr-vlan,netdev=" NETNAME, true);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@ -60,6 +65,9 @@ int main(int argc, char *argv[])
|
||||
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
|
||||
qtest_add_func("pxe/e1000", test_pxe_e1000);
|
||||
qtest_add_func("pxe/virtio", test_pxe_virtio_pci);
|
||||
} else if (strcmp(arch, "ppc64") == 0) {
|
||||
qtest_add_func("pxe/virtio", test_pxe_virtio_pci);
|
||||
qtest_add_func("pxe/spapr-vlan", test_pxe_spapr_vlan);
|
||||
}
|
||||
ret = g_test_run();
|
||||
boot_sector_cleanup(disk);
|
||||
|
@ -42,7 +42,7 @@ static void test_smram_lock(void)
|
||||
QPCIDevice *pcidev;
|
||||
QDict *response;
|
||||
|
||||
pcibus = qpci_init_pc();
|
||||
pcibus = qpci_init_pc(NULL);
|
||||
g_assert(pcibus != NULL);
|
||||
|
||||
pcidev = qpci_device_find(pcibus, 0);
|
||||
|
@ -22,7 +22,7 @@ static void test_rtas_get_time_of_day(void)
|
||||
t2 = mktimegm(&tm);
|
||||
g_assert(t2 - t1 < 5); /* 5 sec max to run the test */
|
||||
|
||||
qtest_spapr_shutdown(qs);
|
||||
qtest_shutdown(qs);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -35,7 +35,7 @@ static QPCIDevice *get_device(void)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
|
||||
pcibus = qpci_init_pc();
|
||||
pcibus = qpci_init_pc(NULL);
|
||||
qpci_device_foreach(pcibus, 0x10ec, 0x8139, save_fn, &dev);
|
||||
g_assert(dev != NULL);
|
||||
|
||||
|
@ -57,7 +57,7 @@ static void test_init(TestData *d)
|
||||
qtest_irq_intercept_in(qs, "ioapic");
|
||||
g_free(s);
|
||||
|
||||
bus = qpci_init_pc();
|
||||
bus = qpci_init_pc(NULL);
|
||||
d->dev = qpci_device_find(bus, QPCI_DEVFN(0x1f, 0x00));
|
||||
g_assert(d->dev != NULL);
|
||||
|
||||
|
@ -56,7 +56,7 @@ static void pci_init(void)
|
||||
if (pcibus) {
|
||||
return;
|
||||
}
|
||||
pcibus = qpci_init_pc();
|
||||
pcibus = qpci_init_pc(NULL);
|
||||
g_assert(pcibus != NULL);
|
||||
|
||||
qusb_pci_init_one(pcibus, &uhci1, QPCI_DEVFN(0x1d, 0), 4);
|
||||
|
@ -9,9 +9,13 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "libqtest.h"
|
||||
#include "libqos/libqos.h"
|
||||
#include "libqos/usb.h"
|
||||
#include "libqos/libqos-pc.h"
|
||||
#include "libqos/libqos-spapr.h"
|
||||
#include "hw/usb/uhci-regs.h"
|
||||
|
||||
static QOSState *qs;
|
||||
|
||||
static void test_uhci_init(void)
|
||||
{
|
||||
@ -19,13 +23,10 @@ static void test_uhci_init(void)
|
||||
|
||||
static void test_port(int port)
|
||||
{
|
||||
QPCIBus *pcibus;
|
||||
struct qhc uhci;
|
||||
|
||||
g_assert(port > 0);
|
||||
pcibus = qpci_init_pc();
|
||||
g_assert(pcibus != NULL);
|
||||
qusb_pci_init_one(pcibus, &uhci, QPCI_DEVFN(0x1d, 0), 4);
|
||||
qusb_pci_init_one(qs->pcibus, &uhci, QPCI_DEVFN(0x1d, 0), 4);
|
||||
uhci_port_test(&uhci, port - 1, UHCI_PORT_CCS);
|
||||
}
|
||||
|
||||
@ -75,6 +76,7 @@ static void test_usb_storage_hotplug(void)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *arch = qtest_get_arch();
|
||||
int ret;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
@ -84,11 +86,17 @@ int main(int argc, char **argv)
|
||||
qtest_add_func("/uhci/pci/hotplug", test_uhci_hotplug);
|
||||
qtest_add_func("/uhci/pci/hotplug/usb-storage", test_usb_storage_hotplug);
|
||||
|
||||
qtest_start("-device piix3-usb-uhci,id=uhci,addr=1d.0"
|
||||
" -drive id=drive0,if=none,file=/dev/null,format=raw"
|
||||
" -device usb-tablet,bus=uhci.0,port=1");
|
||||
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
|
||||
qs = qtest_pc_boot("-device piix3-usb-uhci,id=uhci,addr=1d.0"
|
||||
" -drive id=drive0,if=none,file=/dev/null,format=raw"
|
||||
" -device usb-tablet,bus=uhci.0,port=1");
|
||||
} else if (strcmp(arch, "ppc64") == 0) {
|
||||
qs = qtest_spapr_boot("-device piix3-usb-uhci,id=uhci,addr=1d.0"
|
||||
" -drive id=drive0,if=none,file=/dev/null,format=raw"
|
||||
" -device usb-tablet,bus=uhci.0,port=1");
|
||||
}
|
||||
ret = g_test_run();
|
||||
qtest_end();
|
||||
qtest_shutdown(qs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ static void init_virtio_dev(TestServer *s)
|
||||
QVirtioPCIDevice *dev;
|
||||
uint32_t features;
|
||||
|
||||
bus = qpci_init_pc();
|
||||
bus = qpci_init_pc(NULL);
|
||||
g_assert_nonnull(bus);
|
||||
|
||||
dev = qvirtio_pci_device_find(bus, VIRTIO_ID_NET);
|
||||
@ -884,7 +884,7 @@ static void test_multiqueue(void)
|
||||
qtest_start(cmd);
|
||||
g_free(cmd);
|
||||
|
||||
bus = qpci_init_pc();
|
||||
bus = qpci_init_pc(NULL);
|
||||
dev = virtio_net_pci_init(bus, PCI_SLOT);
|
||||
|
||||
alloc = pc_alloc_init();
|
||||
|
@ -63,7 +63,7 @@ static QVirtIO9P *qvirtio_9p_pci_init(void)
|
||||
|
||||
v9p = g_new0(QVirtIO9P, 1);
|
||||
v9p->alloc = pc_alloc_init();
|
||||
v9p->bus = qpci_init_pc();
|
||||
v9p->bus = qpci_init_pc(NULL);
|
||||
|
||||
dev = qvirtio_pci_device_find(v9p->bus, VIRTIO_ID_9P);
|
||||
g_assert_nonnull(dev);
|
||||
|
@ -75,7 +75,7 @@ static QPCIBus *pci_test_start(void)
|
||||
g_free(tmp_path);
|
||||
g_free(cmdline);
|
||||
|
||||
return qpci_init_pc();
|
||||
return qpci_init_pc(NULL);
|
||||
}
|
||||
|
||||
static void arm_test_start(void)
|
||||
|
@ -62,7 +62,7 @@ static QPCIBus *pci_test_start(int socket)
|
||||
qtest_start(cmdline);
|
||||
g_free(cmdline);
|
||||
|
||||
return qpci_init_pc();
|
||||
return qpci_init_pc(NULL);
|
||||
}
|
||||
|
||||
static void driver_init(const QVirtioBus *bus, QVirtioDevice *dev)
|
||||
|
@ -146,7 +146,7 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
|
||||
|
||||
vs = g_new0(QVirtIOSCSI, 1);
|
||||
vs->alloc = pc_alloc_init();
|
||||
vs->bus = qpci_init_pc();
|
||||
vs->bus = qpci_init_pc(NULL);
|
||||
|
||||
dev = qvirtio_pci_device_find(vs->bus, VIRTIO_ID_SCSI);
|
||||
vs->dev = (QVirtioDevice *)dev;
|
||||
|
Loading…
Reference in New Issue
Block a user