Re: [PATCH V3 13/14] KVM: MIPS: Add more MMIO load/store instructions emulation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



нед, 3. мај 2020. у 12:16 Huacai Chen <chenhc@xxxxxxxxxx> је написао/ла:
>
> This patch add more MMIO load/store instructions emulation, which can
> be observed in QXL and some other device drivers:
>
> 1, LWL, LWR, LDW, LDR, SWL, SWR, SDL and SDR for all MIPS;
> 2, GSLBX, GSLHX, GSLWX, GSLDX, GSSBX, GSSHX, GSSWX and GSSDX for
>    Loongson-3.
>
> Signed-off-by: Huacai Chen <chenhc@xxxxxxxxxx>
> Co-developed-by: Jiaxun Yang <jiaxun.yang@xxxxxxxxxxx>
> ---
>  arch/mips/kvm/emulate.c | 480 +++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 470 insertions(+), 10 deletions(-)
>
> diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
> index 3946499..71316fa 100644
> --- a/arch/mips/kvm/emulate.c
> +++ b/arch/mips/kvm/emulate.c
> @@ -1604,6 +1604,7 @@ enum emulation_result kvm_mips_emulate_store(union mips_instruction inst,
>         enum emulation_result er;
>         u32 rt;
>         void *data = run->mmio.data;
> +       unsigned int imme;
>         unsigned long curr_pc;
>
>         /*
> @@ -1661,6 +1662,211 @@ enum emulation_result kvm_mips_emulate_store(union mips_instruction inst,
>                           vcpu->arch.gprs[rt], *(u8 *)data);
>                 break;
>
> +       case swl_op:
> +               run->mmio.phys_addr = kvm_mips_callbacks->gva_to_gpa(
> +                                       vcpu->arch.host_cp0_badvaddr) & (~0x3);
> +               run->mmio.len = 4;
> +               imme = vcpu->arch.host_cp0_badvaddr & 0x3;
> +               switch (imme) {
> +               case 0:
> +                       *(u32 *)data = ((*(u32 *)data) & 0xffffff00) |
> +                                       (vcpu->arch.gprs[rt] >> 24);
> +                       break;
> +               case 1:
> +                       *(u32 *)data = ((*(u32 *)data) & 0xffff0000) |
> +                                       (vcpu->arch.gprs[rt] >> 16);
> +                       break;
> +               case 2:
> +                       *(u32 *)data = ((*(u32 *)data) & 0xff000000) |
> +                                       (vcpu->arch.gprs[rt] >> 8);
> +                       break;
> +               case 3:
> +                       *(u32 *)data = vcpu->arch.gprs[rt];
> +                       break;
> +               default:
> +                       break;
> +               }
> +
> +               kvm_debug("[%#lx] OP_SWL: eaddr: %#lx, gpr: %#lx, data: %#x\n",
> +                         vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
> +                         vcpu->arch.gprs[rt], *(u32 *)data);
> +               break;
> +
> +       case swr_op:
> +               run->mmio.phys_addr = kvm_mips_callbacks->gva_to_gpa(
> +                                       vcpu->arch.host_cp0_badvaddr) & (~0x3);
> +               run->mmio.len = 4;
> +               imme = vcpu->arch.host_cp0_badvaddr & 0x3;
> +               switch (imme) {
> +               case 0:
> +                       *(u32 *)data = vcpu->arch.gprs[rt];
> +                       break;
> +               case 1:
> +                       *(u32 *)data = ((*(u32 *)data) & 0xff) |
> +                                       (vcpu->arch.gprs[rt] << 8);
> +                       break;
> +               case 2:
> +                       *(u32 *)data = ((*(u32 *)data) & 0xffff) |
> +                                       (vcpu->arch.gprs[rt] << 16);
> +                       break;
> +               case 3:
> +                       *(u32 *)data = ((*(u32 *)data) & 0xffffff) |
> +                                       (vcpu->arch.gprs[rt] << 24);
> +                       break;
> +               default:
> +                       break;
> +               }
> +
> +               kvm_debug("[%#lx] OP_SWR: eaddr: %#lx, gpr: %#lx, data: %#x\n",
> +                         vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
> +                         vcpu->arch.gprs[rt], *(u32 *)data);
> +               break;
> +
> +       case sdl_op:
> +               run->mmio.phys_addr = kvm_mips_callbacks->gva_to_gpa(
> +                                       vcpu->arch.host_cp0_badvaddr) & (~0x7);
> +
> +               run->mmio.len = 8;
> +               imme = vcpu->arch.host_cp0_badvaddr & 0x7;
> +               switch (imme) {
> +               case 0:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xffffffffffffff00) |
> +                                       ((vcpu->arch.gprs[rt] >> 56) & 0xff);
> +                       break;
> +               case 1:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xffffffffffff0000) |
> +                                       ((vcpu->arch.gprs[rt] >> 48) & 0xffff);
> +                       break;
> +               case 2:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xffffffffff000000) |
> +                                       ((vcpu->arch.gprs[rt] >> 40) & 0xffffff);
> +                       break;
> +               case 3:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xffffffff00000000) |
> +                                       ((vcpu->arch.gprs[rt] >> 32) & 0xffffffff);
> +                       break;
> +               case 4:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xffffff0000000000) |
> +                                       ((vcpu->arch.gprs[rt] >> 24) & 0xffffffffff);
> +                       break;
> +               case 5:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xffff000000000000) |
> +                                       ((vcpu->arch.gprs[rt] >> 16) & 0xffffffffffff);
> +                       break;
> +               case 6:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xff00000000000000) |
> +                                       ((vcpu->arch.gprs[rt] >> 8) & 0xffffffffffffff);
> +                       break;
> +               case 7:
> +                       *(u64 *)data = vcpu->arch.gprs[rt];
> +                       break;
> +               default:
> +                       break;
> +               }
> +
> +               kvm_debug("[%#lx] OP_SDL: eaddr: %#lx, gpr: %#lx, data: %llx\n",
> +                         vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
> +                         vcpu->arch.gprs[rt], *(u64 *)data);
> +               break;
> +
> +       case sdr_op:
> +               run->mmio.phys_addr = kvm_mips_callbacks->gva_to_gpa(
> +                                       vcpu->arch.host_cp0_badvaddr) & (~0x7);
> +
> +               run->mmio.len = 8;
> +               imme = vcpu->arch.host_cp0_badvaddr & 0x7;
> +               switch (imme) {
> +               case 0:
> +                       *(u64 *)data = vcpu->arch.gprs[rt];
> +                       break;
> +               case 1:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xff) |
> +                                       (vcpu->arch.gprs[rt] << 8);
> +                       break;
> +               case 2:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xffff) |
> +                                       (vcpu->arch.gprs[rt] << 16);
> +                       break;
> +               case 3:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xffffff) |
> +                                       (vcpu->arch.gprs[rt] << 24);
> +                       break;
> +               case 4:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xffffffff) |
> +                                       (vcpu->arch.gprs[rt] << 32);
> +                       break;
> +               case 5:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xffffffffff) |
> +                                       (vcpu->arch.gprs[rt] << 40);
> +                       break;
> +               case 6:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xffffffffffff) |
> +                                       (vcpu->arch.gprs[rt] << 48);
> +                       break;
> +               case 7:
> +                       *(u64 *)data = ((*(u64 *)data) & 0xffffffffffffff) |
> +                                       (vcpu->arch.gprs[rt] << 56);
> +                       break;
> +               default:
> +                       break;
> +               }
> +
> +               kvm_debug("[%#lx] OP_SDR: eaddr: %#lx, gpr: %#lx, data: %llx\n",
> +                         vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
> +                         vcpu->arch.gprs[rt], *(u64 *)data);
> +               break;
> +
> +#ifdef CONFIG_CPU_LOONGSON64
> +       case sdc2_op:
> +               rt = inst.loongson3_lsdc2_format.rt;
> +               switch (inst.loongson3_lsdc2_format.opcode1) {
> +               /*
> +                * Loongson-3 overridden sdc2 instructions.
> +                * opcode1              instruction
> +                *   0x0          gssbx: store 1 bytes from GPR
> +                *   0x1          gsshx: store 2 bytes from GPR
> +                *   0x2          gsswx: store 4 bytes from GPR
> +                *   0x3          gssdx: store 8 bytes from GPR
> +                */
> +               case 0x0:
> +                       run->mmio.len = 1;
> +                       *(u8 *)data = vcpu->arch.gprs[rt];
> +
> +                       kvm_debug("[%#lx] OP_GSSBX: eaddr: %#lx, gpr: %#lx, data: %#x\n",
> +                                 vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
> +                                 vcpu->arch.gprs[rt], *(u8 *)data);
> +                       break;
> +               case 0x1:
> +                       run->mmio.len = 2;
> +                       *(u16 *)data = vcpu->arch.gprs[rt];
> +
> +                       kvm_debug("[%#lx] OP_GSSSHX: eaddr: %#lx, gpr: %#lx, data: %#x\n",
> +                                 vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
> +                                 vcpu->arch.gprs[rt], *(u16 *)data);
> +                       break;
> +               case 0x2:
> +                       run->mmio.len = 4;
> +                       *(u32 *)data = vcpu->arch.gprs[rt];
> +
> +                       kvm_debug("[%#lx] OP_GSSWX: eaddr: %#lx, gpr: %#lx, data: %#x\n",
> +                                 vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
> +                                 vcpu->arch.gprs[rt], *(u32 *)data);
> +                       break;
> +               case 0x3:
> +                       run->mmio.len = 8;
> +                       *(u64 *)data = vcpu->arch.gprs[rt];
> +
> +                       kvm_debug("[%#lx] OP_GSSDX: eaddr: %#lx, gpr: %#lx, data: %#llx\n",
> +                                 vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
> +                                 vcpu->arch.gprs[rt], *(u64 *)data);
> +                       break;
> +               default:
> +                       kvm_err("Godson Exteneded GS-Store not yet supported (inst=0x%08x)\n",
> +                               inst.word);
> +                       break;
> +               }
> +               break;
> +#endif
>         default:
>                 kvm_err("Store not yet supported (inst=0x%08x)\n",
>                         inst.word);
> @@ -1695,6 +1901,7 @@ enum emulation_result kvm_mips_emulate_load(union mips_instruction inst,
>         enum emulation_result er;
>         unsigned long curr_pc;
>         u32 op, rt;
> +       unsigned int imme;
>
>         rt = inst.i_format.rt;
>         op = inst.i_format.opcode;
> @@ -1747,6 +1954,162 @@ enum emulation_result kvm_mips_emulate_load(union mips_instruction inst,
>                 run->mmio.len = 1;
>                 break;
>
> +       case lwl_op:
> +               run->mmio.phys_addr = kvm_mips_callbacks->gva_to_gpa(
> +                                       vcpu->arch.host_cp0_badvaddr) & (~0x3);
> +
> +               run->mmio.len = 4;
> +               imme = vcpu->arch.host_cp0_badvaddr & 0x3;
> +               switch (imme) {
> +               case 0:
> +                       vcpu->mmio_needed = 3;  /* 1 byte */
> +                       break;
> +               case 1:
> +                       vcpu->mmio_needed = 4;  /* 2 bytes */
> +                       break;
> +               case 2:
> +                       vcpu->mmio_needed = 5;  /* 3 bytes */
> +                       break;
> +               case 3:
> +                       vcpu->mmio_needed = 6;  /* 4 bytes */
> +                       break;
> +               default:
> +                       break;
> +               }
> +               break;
> +
> +       case lwr_op:
> +               run->mmio.phys_addr = kvm_mips_callbacks->gva_to_gpa(
> +                                       vcpu->arch.host_cp0_badvaddr) & (~0x3);
> +
> +               run->mmio.len = 4;
> +               imme = vcpu->arch.host_cp0_badvaddr & 0x3;
> +               switch (imme) {
> +               case 0:
> +                       vcpu->mmio_needed = 7;  /* 4 bytes */
> +                       break;
> +               case 1:
> +                       vcpu->mmio_needed = 8;  /* 3 bytes */
> +                       break;
> +               case 2:
> +                       vcpu->mmio_needed = 9;  /* 2 bytes */
> +                       break;
> +               case 3:
> +                       vcpu->mmio_needed = 10; /* 1 byte */
> +                       break;
> +               default:
> +                       break;
> +               }
> +               break;
> +
> +       case ldl_op:
> +               run->mmio.phys_addr = kvm_mips_callbacks->gva_to_gpa(
> +                                       vcpu->arch.host_cp0_badvaddr) & (~0x7);
> +
> +               run->mmio.len = 8;
> +               imme = vcpu->arch.host_cp0_badvaddr & 0x7;
> +               switch (imme) {
> +               case 0:
> +                       vcpu->mmio_needed = 11; /* 1 byte */
> +                       break;
> +               case 1:
> +                       vcpu->mmio_needed = 12; /* 2 bytes */
> +                       break;
> +               case 2:
> +                       vcpu->mmio_needed = 13; /* 3 bytes */
> +                       break;
> +               case 3:
> +                       vcpu->mmio_needed = 14; /* 4 bytes */
> +                       break;
> +               case 4:
> +                       vcpu->mmio_needed = 15; /* 5 bytes */
> +                       break;
> +               case 5:
> +                       vcpu->mmio_needed = 16; /* 6 bytes */
> +                       break;
> +               case 6:
> +                       vcpu->mmio_needed = 17; /* 7 bytes */
> +                       break;
> +               case 7:
> +                       vcpu->mmio_needed = 18; /* 8 bytes */
> +                       break;
> +               default:
> +                       break;
> +               }
> +               break;
> +
> +       case ldr_op:
> +               run->mmio.phys_addr = kvm_mips_callbacks->gva_to_gpa(
> +                                       vcpu->arch.host_cp0_badvaddr) & (~0x7);
> +
> +               run->mmio.len = 8;
> +               imme = vcpu->arch.host_cp0_badvaddr & 0x7;
> +               switch (imme) {
> +               case 0:
> +                       vcpu->mmio_needed = 19; /* 8 bytes */
> +                       break;
> +               case 1:
> +                       vcpu->mmio_needed = 20; /* 7 bytes */
> +                       break;
> +               case 2:
> +                       vcpu->mmio_needed = 21; /* 6 bytes */
> +                       break;
> +               case 3:
> +                       vcpu->mmio_needed = 22; /* 5 bytes */
> +                       break;
> +               case 4:
> +                       vcpu->mmio_needed = 23; /* 4 bytes */
> +                       break;
> +               case 5:
> +                       vcpu->mmio_needed = 24; /* 3 bytes */
> +                       break;
> +               case 6:
> +                       vcpu->mmio_needed = 25; /* 2 bytes */
> +                       break;
> +               case 7:
> +                       vcpu->mmio_needed = 26; /* 1 byte */
> +                       break;
> +               default:
> +                       break;
> +               }
> +               break;
> +
> +#ifdef CONFIG_CPU_LOONGSON64
> +       case ldc2_op:
> +               rt = inst.loongson3_lsdc2_format.rt;
> +               switch (inst.loongson3_lsdc2_format.opcode1) {
> +               /*
> +                * Loongson-3 overridden ldc2 instructions.
> +                * opcode1              instruction
> +                *   0x0          gslbx: store 1 bytes from GPR
> +                *   0x1          gslhx: store 2 bytes from GPR
> +                *   0x2          gslwx: store 4 bytes from GPR
> +                *   0x3          gsldx: store 8 bytes from GPR
> +                */
> +               case 0x0:
> +                       run->mmio.len = 1;
> +                       vcpu->mmio_needed = 27; /* signed */
> +                       break;
> +               case 0x1:
> +                       run->mmio.len = 2;
> +                       vcpu->mmio_needed = 28; /* signed */
> +                       break;
> +               case 0x2:
> +                       run->mmio.len = 4;
> +                       vcpu->mmio_needed = 29; /* signed */
> +                       break;
> +               case 0x3:
> +                       run->mmio.len = 8;
> +                       vcpu->mmio_needed = 30; /* signed */
> +                       break;
> +               default:
> +                       kvm_err("Godson Exteneded GS-Load for float not yet supported (inst=0x%08x)\n",
> +                               inst.word);
> +                       break;
> +               }
> +               break;
> +#endif
> +
>         default:
>                 kvm_err("Load not yet supported (inst=0x%08x)\n",
>                         inst.word);
> @@ -2612,28 +2975,125 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
>
>         switch (run->mmio.len) {
>         case 8:
> -               *gpr = *(s64 *)run->mmio.data;
> +               switch (vcpu->mmio_needed) {
> +               case 11:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffffffffffff) |
> +                               (((*(s64 *)run->mmio.data) & 0xff) << 56);
> +                       break;
> +               case 12:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffffffffff) |
> +                               (((*(s64 *)run->mmio.data) & 0xffff) << 48);
> +                       break;
> +               case 13:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffffffff) |
> +                               (((*(s64 *)run->mmio.data) & 0xffffff) << 40);
> +                       break;
> +               case 14:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffffff) |
> +                               (((*(s64 *)run->mmio.data) & 0xffffffff) << 32);
> +                       break;
> +               case 15:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffff) |
> +                               (((*(s64 *)run->mmio.data) & 0xffffffffff) << 24);
> +                       break;
> +               case 16:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffff) |
> +                               (((*(s64 *)run->mmio.data) & 0xffffffffffff) << 16);
> +                       break;
> +               case 17:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xff) |
> +                               (((*(s64 *)run->mmio.data) & 0xffffffffffffff) << 8);
> +                       break;
> +               case 18:
> +               case 19:
> +                       *gpr = *(s64 *)run->mmio.data;
> +                       break;
> +               case 20:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xff00000000000000) |
> +                               ((((*(s64 *)run->mmio.data)) >> 8) & 0xffffffffffffff);
> +                       break;
> +               case 21:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffff000000000000) |
> +                               ((((*(s64 *)run->mmio.data)) >> 16) & 0xffffffffffff);
> +                       break;
> +               case 22:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffff0000000000) |
> +                               ((((*(s64 *)run->mmio.data)) >> 24) & 0xffffffffff);
> +                       break;
> +               case 23:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffffff00000000) |
> +                               ((((*(s64 *)run->mmio.data)) >> 32) & 0xffffffff);
> +                       break;
> +               case 24:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffffffff000000) |
> +                               ((((*(s64 *)run->mmio.data)) >> 40) & 0xffffff);
> +                       break;
> +               case 25:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffffffffff0000) |
> +                               ((((*(s64 *)run->mmio.data)) >> 48) & 0xffff);
> +                       break;
> +               case 26:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffffffffffff00) |
> +                               ((((*(s64 *)run->mmio.data)) >> 56) & 0xff);
> +                       break;
> +               default:
> +                       *gpr = *(s64 *)run->mmio.data;
> +               }
>                 break;
>
>         case 4:
> -               if (vcpu->mmio_needed == 2)
> -                       *gpr = *(s32 *)run->mmio.data;
> -               else
> +               switch (vcpu->mmio_needed) {
> +               case 1:
>                         *gpr = *(u32 *)run->mmio.data;
> +                       break;
> +               case 2:
> +                       *gpr = *(s32 *)run->mmio.data;
> +                       break;
> +               case 3:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffff) |
> +                               (((*(s32 *)run->mmio.data) & 0xff) << 24);
> +                       break;
> +               case 4:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffff) |
> +                               (((*(s32 *)run->mmio.data) & 0xffff) << 16);
> +                       break;
> +               case 5:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xff) |
> +                               (((*(s32 *)run->mmio.data) & 0xffffff) << 8);
> +                       break;
> +               case 6:
> +               case 7:
> +                       *gpr = *(s32 *)run->mmio.data;
> +                       break;
> +               case 8:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xff000000) |
> +                               ((((*(s32 *)run->mmio.data)) >> 8) & 0xffffff);
> +                       break;
> +               case 9:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffff0000) |
> +                               ((((*(s32 *)run->mmio.data)) >> 16) & 0xffff);
> +                       break;
> +               case 10:
> +                       *gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffff00) |
> +                               ((((*(s32 *)run->mmio.data)) >> 24) & 0xff);
> +                       break;
> +               default:
> +                       *gpr = *(s32 *)run->mmio.data;
> +               }
>                 break;
>
>         case 2:
> -               if (vcpu->mmio_needed == 2)
> -                       *gpr = *(s16 *) run->mmio.data;
> -               else
> +               if (vcpu->mmio_needed == 1)
>                         *gpr = *(u16 *)run->mmio.data;
> +               else
> +                       *gpr = *(s16 *)run->mmio.data;
>
>                 break;
>         case 1:
> -               if (vcpu->mmio_needed == 2)
> -                       *gpr = *(s8 *) run->mmio.data;
> +               if (vcpu->mmio_needed == 1)
> +                       *gpr = *(u8 *)run->mmio.data;
>                 else
> -                       *gpr = *(u8 *) run->mmio.data;
> +                       *gpr = *(s8 *)run->mmio.data;
>                 break;
>         }
>
> --
> 2.7.0
>

Reviewed-by: Aleksandar Markovic <aleksandar.qemu.devel@xxxxxxxxx>




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux